]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
break the net connection AFTER calling ClientDisconnect; this fixes issues with clien...
[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_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 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)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 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"};
78 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"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 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"};
81 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"};
82 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"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 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)"};
91 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)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 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."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 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."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 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"};
114 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"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
119 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
120 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"};
121
122 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
123 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
124 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
125 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
126 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
127 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
128 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
129 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130
131 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)"};
132 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"};
133
134 cvar_t r_texture_sRGB_2d = {0, "r_texture_sRGB_2d", "0", "load textures as sRGB"};
135 cvar_t r_texture_sRGB_skin_diffuse = {0, "r_texture_sRGB_skin_diffuse", "0", "load textures as sRGB"};
136 cvar_t r_texture_sRGB_skin_gloss = {0, "r_texture_sRGB_skin_gloss", "0", "load textures as sRGB"};
137 cvar_t r_texture_sRGB_skin_glow = {0, "r_texture_sRGB_skin_glow", "0", "load textures as sRGB"};
138 cvar_t r_texture_sRGB_skin_reflect = {0, "r_texture_sRGB_skin_reflect", "0", "load textures as sRGB"};
139 cvar_t r_texture_sRGB_cubemap = {0, "r_texture_sRGB_cubemap", "0", "load textures as sRGB"};
140 cvar_t r_texture_sRGB_skybox = {0, "r_texture_sRGB_skybox", "0", "load textures as sRGB"};
141
142 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
143 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
144 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
145
146 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"};
147 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"};
148 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
149 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
150 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"};
151 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)"};
152 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)"};
153 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
154
155 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)"};
156 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
157 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)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
159 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)"};
160 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
161 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
162 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)"};
163 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)"};
164 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)"};
165 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)"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
170
171 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)"};
172 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
173 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"};
174 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
175 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
176 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
177
178 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
179 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
180 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
181 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
182
183 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
184 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
185 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
186 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
187 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
188 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
189 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
190
191 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
192 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
193 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
194 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)"};
195 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
196 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
197 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
199 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
200 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
201
202 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"};
203
204 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"};
205
206 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
207
208 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
209 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"};
210 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
211 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
212 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
213 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
214 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)"};
215 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
216 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
217
218 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
219 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"};
220
221 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."};
222
223 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)"};
224
225 extern cvar_t v_glslgamma;
226
227 extern qboolean v_flipped_state;
228
229 static struct r_bloomstate_s
230 {
231         qboolean enabled;
232         qboolean hdr;
233
234         int bloomwidth, bloomheight;
235
236         textype_t texturetype;
237         int viewfbo; // used to check if r_viewfbo cvar has changed
238
239         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
240         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
241         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
242
243         int screentexturewidth, screentextureheight;
244         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
245
246         int bloomtexturewidth, bloomtextureheight;
247         rtexture_t *texture_bloom;
248
249         // arrays for rendering the screen passes
250         float screentexcoord2f[8];
251         float bloomtexcoord2f[8];
252         float offsettexcoord2f[8];
253
254         r_viewport_t viewport;
255 }
256 r_bloomstate;
257
258 r_waterstate_t r_waterstate;
259
260 /// shadow volume bsp struct with automatically growing nodes buffer
261 svbsp_t r_svbsp;
262
263 rtexture_t *r_texture_blanknormalmap;
264 rtexture_t *r_texture_white;
265 rtexture_t *r_texture_grey128;
266 rtexture_t *r_texture_black;
267 rtexture_t *r_texture_notexture;
268 rtexture_t *r_texture_whitecube;
269 rtexture_t *r_texture_normalizationcube;
270 rtexture_t *r_texture_fogattenuation;
271 rtexture_t *r_texture_fogheighttexture;
272 rtexture_t *r_texture_gammaramps;
273 unsigned int r_texture_gammaramps_serial;
274 //rtexture_t *r_texture_fogintensity;
275 rtexture_t *r_texture_reflectcube;
276
277 // TODO: hash lookups?
278 typedef struct cubemapinfo_s
279 {
280         char basename[64];
281         rtexture_t *texture;
282 }
283 cubemapinfo_t;
284
285 int r_texture_numcubemaps;
286 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
287
288 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
289 unsigned int r_numqueries;
290 unsigned int r_maxqueries;
291
292 typedef struct r_qwskincache_s
293 {
294         char name[MAX_QPATH];
295         skinframe_t *skinframe;
296 }
297 r_qwskincache_t;
298
299 static r_qwskincache_t *r_qwskincache;
300 static int r_qwskincache_size;
301
302 /// vertex coordinates for a quad that covers the screen exactly
303 extern const float r_screenvertex3f[12];
304 extern const float r_d3dscreenvertex3f[12];
305 const float r_screenvertex3f[12] =
306 {
307         0, 0, 0,
308         1, 0, 0,
309         1, 1, 0,
310         0, 1, 0
311 };
312 const float r_d3dscreenvertex3f[12] =
313 {
314         0, 1, 0,
315         1, 1, 0,
316         1, 0, 0,
317         0, 0, 0
318 };
319
320 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
321 {
322         int i;
323         for (i = 0;i < verts;i++)
324         {
325                 out[0] = in[0] * r;
326                 out[1] = in[1] * g;
327                 out[2] = in[2] * b;
328                 out[3] = in[3];
329                 in += 4;
330                 out += 4;
331         }
332 }
333
334 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
335 {
336         int i;
337         for (i = 0;i < verts;i++)
338         {
339                 out[0] = r;
340                 out[1] = g;
341                 out[2] = b;
342                 out[3] = a;
343                 out += 4;
344         }
345 }
346
347 // FIXME: move this to client?
348 void FOG_clear(void)
349 {
350         if (gamemode == GAME_NEHAHRA)
351         {
352                 Cvar_Set("gl_fogenable", "0");
353                 Cvar_Set("gl_fogdensity", "0.2");
354                 Cvar_Set("gl_fogred", "0.3");
355                 Cvar_Set("gl_foggreen", "0.3");
356                 Cvar_Set("gl_fogblue", "0.3");
357         }
358         r_refdef.fog_density = 0;
359         r_refdef.fog_red = 0;
360         r_refdef.fog_green = 0;
361         r_refdef.fog_blue = 0;
362         r_refdef.fog_alpha = 1;
363         r_refdef.fog_start = 0;
364         r_refdef.fog_end = 16384;
365         r_refdef.fog_height = 1<<30;
366         r_refdef.fog_fadedepth = 128;
367         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
368 }
369
370 static void R_BuildBlankTextures(void)
371 {
372         unsigned char data[4];
373         data[2] = 128; // normal X
374         data[1] = 128; // normal Y
375         data[0] = 255; // normal Z
376         data[3] = 128; // height
377         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
378         data[0] = 255;
379         data[1] = 255;
380         data[2] = 255;
381         data[3] = 255;
382         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
383         data[0] = 128;
384         data[1] = 128;
385         data[2] = 128;
386         data[3] = 255;
387         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
388         data[0] = 0;
389         data[1] = 0;
390         data[2] = 0;
391         data[3] = 255;
392         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 }
394
395 static void R_BuildNoTexture(void)
396 {
397         int x, y;
398         unsigned char pix[16][16][4];
399         // this makes a light grey/dark grey checkerboard texture
400         for (y = 0;y < 16;y++)
401         {
402                 for (x = 0;x < 16;x++)
403                 {
404                         if ((y < 8) ^ (x < 8))
405                         {
406                                 pix[y][x][0] = 128;
407                                 pix[y][x][1] = 128;
408                                 pix[y][x][2] = 128;
409                                 pix[y][x][3] = 255;
410                         }
411                         else
412                         {
413                                 pix[y][x][0] = 64;
414                                 pix[y][x][1] = 64;
415                                 pix[y][x][2] = 64;
416                                 pix[y][x][3] = 255;
417                         }
418                 }
419         }
420         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
421 }
422
423 static void R_BuildWhiteCube(void)
424 {
425         unsigned char data[6*1*1*4];
426         memset(data, 255, sizeof(data));
427         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
428 }
429
430 static void R_BuildNormalizationCube(void)
431 {
432         int x, y, side;
433         vec3_t v;
434         vec_t s, t, intensity;
435 #define NORMSIZE 64
436         unsigned char *data;
437         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
438         for (side = 0;side < 6;side++)
439         {
440                 for (y = 0;y < NORMSIZE;y++)
441                 {
442                         for (x = 0;x < NORMSIZE;x++)
443                         {
444                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
445                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
446                                 switch(side)
447                                 {
448                                 default:
449                                 case 0:
450                                         v[0] = 1;
451                                         v[1] = -t;
452                                         v[2] = -s;
453                                         break;
454                                 case 1:
455                                         v[0] = -1;
456                                         v[1] = -t;
457                                         v[2] = s;
458                                         break;
459                                 case 2:
460                                         v[0] = s;
461                                         v[1] = 1;
462                                         v[2] = t;
463                                         break;
464                                 case 3:
465                                         v[0] = s;
466                                         v[1] = -1;
467                                         v[2] = -t;
468                                         break;
469                                 case 4:
470                                         v[0] = s;
471                                         v[1] = -t;
472                                         v[2] = 1;
473                                         break;
474                                 case 5:
475                                         v[0] = -s;
476                                         v[1] = -t;
477                                         v[2] = -1;
478                                         break;
479                                 }
480                                 intensity = 127.0f / sqrt(DotProduct(v, v));
481                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
482                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
483                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
484                                 data[((side*64+y)*64+x)*4+3] = 255;
485                         }
486                 }
487         }
488         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
489         Mem_Free(data);
490 }
491
492 static void R_BuildFogTexture(void)
493 {
494         int x, b;
495 #define FOGWIDTH 256
496         unsigned char data1[FOGWIDTH][4];
497         //unsigned char data2[FOGWIDTH][4];
498         double d, r, alpha;
499
500         r_refdef.fogmasktable_start = r_refdef.fog_start;
501         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
502         r_refdef.fogmasktable_range = r_refdef.fogrange;
503         r_refdef.fogmasktable_density = r_refdef.fog_density;
504
505         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
506         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
507         {
508                 d = (x * r - r_refdef.fogmasktable_start);
509                 if(developer_extra.integer)
510                         Con_DPrintf("%f ", d);
511                 d = max(0, d);
512                 if (r_fog_exp2.integer)
513                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
514                 else
515                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
516                 if(developer_extra.integer)
517                         Con_DPrintf(" : %f ", alpha);
518                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
519                 if(developer_extra.integer)
520                         Con_DPrintf(" = %f\n", alpha);
521                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
522         }
523
524         for (x = 0;x < FOGWIDTH;x++)
525         {
526                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
527                 data1[x][0] = b;
528                 data1[x][1] = b;
529                 data1[x][2] = b;
530                 data1[x][3] = 255;
531                 //data2[x][0] = 255 - b;
532                 //data2[x][1] = 255 - b;
533                 //data2[x][2] = 255 - b;
534                 //data2[x][3] = 255;
535         }
536         if (r_texture_fogattenuation)
537         {
538                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
539                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
540         }
541         else
542         {
543                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
544                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
545         }
546 }
547
548 static void R_BuildFogHeightTexture(void)
549 {
550         unsigned char *inpixels;
551         int size;
552         int x;
553         int y;
554         int j;
555         float c[4];
556         float f;
557         inpixels = NULL;
558         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
559         if (r_refdef.fogheighttexturename[0])
560                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
561         if (!inpixels)
562         {
563                 r_refdef.fog_height_tablesize = 0;
564                 if (r_texture_fogheighttexture)
565                         R_FreeTexture(r_texture_fogheighttexture);
566                 r_texture_fogheighttexture = NULL;
567                 if (r_refdef.fog_height_table2d)
568                         Mem_Free(r_refdef.fog_height_table2d);
569                 r_refdef.fog_height_table2d = NULL;
570                 if (r_refdef.fog_height_table1d)
571                         Mem_Free(r_refdef.fog_height_table1d);
572                 r_refdef.fog_height_table1d = NULL;
573                 return;
574         }
575         size = image_width;
576         r_refdef.fog_height_tablesize = size;
577         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
578         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
579         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
580         Mem_Free(inpixels);
581         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
582         // average fog color table accounting for every fog layer between a point
583         // and the camera.  (Note: attenuation is handled separately!)
584         for (y = 0;y < size;y++)
585         {
586                 for (x = 0;x < size;x++)
587                 {
588                         Vector4Clear(c);
589                         f = 0;
590                         if (x < y)
591                         {
592                                 for (j = x;j <= y;j++)
593                                 {
594                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
595                                         f++;
596                                 }
597                         }
598                         else
599                         {
600                                 for (j = x;j >= y;j--)
601                                 {
602                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
603                                         f++;
604                                 }
605                         }
606                         f = 1.0f / f;
607                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
609                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
610                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
611                 }
612         }
613         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
614 }
615
616 //=======================================================================================================================================================
617
618 static const char *builtinshaderstring =
619 #include "shader_glsl.h"
620 ;
621
622 const char *builtinhlslshaderstring =
623 #include "shader_hlsl.h"
624 ;
625
626 char *glslshaderstring = NULL;
627 char *hlslshaderstring = NULL;
628
629 //=======================================================================================================================================================
630
631 typedef struct shaderpermutationinfo_s
632 {
633         const char *pretext;
634         const char *name;
635 }
636 shaderpermutationinfo_t;
637
638 typedef struct shadermodeinfo_s
639 {
640         const char *vertexfilename;
641         const char *geometryfilename;
642         const char *fragmentfilename;
643         const char *pretext;
644         const char *name;
645 }
646 shadermodeinfo_t;
647
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
650 {
651         {"#define USEDIFFUSE\n", " diffuse"},
652         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653         {"#define USEVIEWTINT\n", " viewtint"},
654         {"#define USECOLORMAPPING\n", " colormapping"},
655         {"#define USESATURATION\n", " saturation"},
656         {"#define USEFOGINSIDE\n", " foginside"},
657         {"#define USEFOGOUTSIDE\n", " fogoutside"},
658         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660         {"#define USEGAMMARAMPS\n", " gammaramps"},
661         {"#define USECUBEFILTER\n", " cubefilter"},
662         {"#define USEGLOW\n", " glow"},
663         {"#define USEBLOOM\n", " bloom"},
664         {"#define USESPECULAR\n", " specular"},
665         {"#define USEPOSTPROCESSING\n", " postprocessing"},
666         {"#define USEREFLECTION\n", " reflection"},
667         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
671         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
672         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
673         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
674         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
675         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
676         {"#define USEALPHAKILL\n", " alphakill"},
677         {"#define USEREFLECTCUBE\n", " reflectcube"},
678         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
679         {"#define USEBOUNCEGRID\n", " bouncegrid"},
680         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
681 };
682
683 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
684 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
685 {
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
688         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 };
703
704 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
705 {
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
722 };
723
724 struct r_glsl_permutation_s;
725 typedef struct r_glsl_permutation_s
726 {
727         /// hash lookup data
728         struct r_glsl_permutation_s *hashnext;
729         unsigned int mode;
730         unsigned int permutation;
731
732         /// indicates if we have tried compiling this permutation already
733         qboolean compiled;
734         /// 0 if compilation failed
735         int program;
736         // texture units assigned to each detected uniform
737         int tex_Texture_First;
738         int tex_Texture_Second;
739         int tex_Texture_GammaRamps;
740         int tex_Texture_Normal;
741         int tex_Texture_Color;
742         int tex_Texture_Gloss;
743         int tex_Texture_Glow;
744         int tex_Texture_SecondaryNormal;
745         int tex_Texture_SecondaryColor;
746         int tex_Texture_SecondaryGloss;
747         int tex_Texture_SecondaryGlow;
748         int tex_Texture_Pants;
749         int tex_Texture_Shirt;
750         int tex_Texture_FogHeightTexture;
751         int tex_Texture_FogMask;
752         int tex_Texture_Lightmap;
753         int tex_Texture_Deluxemap;
754         int tex_Texture_Attenuation;
755         int tex_Texture_Cube;
756         int tex_Texture_Refraction;
757         int tex_Texture_Reflection;
758         int tex_Texture_ShadowMap2D;
759         int tex_Texture_CubeProjection;
760         int tex_Texture_ScreenDepth;
761         int tex_Texture_ScreenNormalMap;
762         int tex_Texture_ScreenDiffuse;
763         int tex_Texture_ScreenSpecular;
764         int tex_Texture_ReflectMask;
765         int tex_Texture_ReflectCube;
766         int tex_Texture_BounceGrid;
767         /// locations of detected uniforms in program object, or -1 if not found
768         int loc_Texture_First;
769         int loc_Texture_Second;
770         int loc_Texture_GammaRamps;
771         int loc_Texture_Normal;
772         int loc_Texture_Color;
773         int loc_Texture_Gloss;
774         int loc_Texture_Glow;
775         int loc_Texture_SecondaryNormal;
776         int loc_Texture_SecondaryColor;
777         int loc_Texture_SecondaryGloss;
778         int loc_Texture_SecondaryGlow;
779         int loc_Texture_Pants;
780         int loc_Texture_Shirt;
781         int loc_Texture_FogHeightTexture;
782         int loc_Texture_FogMask;
783         int loc_Texture_Lightmap;
784         int loc_Texture_Deluxemap;
785         int loc_Texture_Attenuation;
786         int loc_Texture_Cube;
787         int loc_Texture_Refraction;
788         int loc_Texture_Reflection;
789         int loc_Texture_ShadowMap2D;
790         int loc_Texture_CubeProjection;
791         int loc_Texture_ScreenDepth;
792         int loc_Texture_ScreenNormalMap;
793         int loc_Texture_ScreenDiffuse;
794         int loc_Texture_ScreenSpecular;
795         int loc_Texture_ReflectMask;
796         int loc_Texture_ReflectCube;
797         int loc_Texture_BounceGrid;
798         int loc_Alpha;
799         int loc_BloomBlur_Parameters;
800         int loc_ClientTime;
801         int loc_Color_Ambient;
802         int loc_Color_Diffuse;
803         int loc_Color_Specular;
804         int loc_Color_Glow;
805         int loc_Color_Pants;
806         int loc_Color_Shirt;
807         int loc_DeferredColor_Ambient;
808         int loc_DeferredColor_Diffuse;
809         int loc_DeferredColor_Specular;
810         int loc_DeferredMod_Diffuse;
811         int loc_DeferredMod_Specular;
812         int loc_DistortScaleRefractReflect;
813         int loc_EyePosition;
814         int loc_FogColor;
815         int loc_FogHeightFade;
816         int loc_FogPlane;
817         int loc_FogPlaneViewDist;
818         int loc_FogRangeRecip;
819         int loc_LightColor;
820         int loc_LightDir;
821         int loc_LightPosition;
822         int loc_OffsetMapping_ScaleSteps;
823         int loc_PixelSize;
824         int loc_ReflectColor;
825         int loc_ReflectFactor;
826         int loc_ReflectOffset;
827         int loc_RefractColor;
828         int loc_Saturation;
829         int loc_ScreenCenterRefractReflect;
830         int loc_ScreenScaleRefractReflect;
831         int loc_ScreenToDepth;
832         int loc_ShadowMap_Parameters;
833         int loc_ShadowMap_TextureScale;
834         int loc_SpecularPower;
835         int loc_UserVec1;
836         int loc_UserVec2;
837         int loc_UserVec3;
838         int loc_UserVec4;
839         int loc_ViewTintColor;
840         int loc_ViewToLight;
841         int loc_ModelToLight;
842         int loc_TexMatrix;
843         int loc_BackgroundTexMatrix;
844         int loc_ModelViewProjectionMatrix;
845         int loc_ModelViewMatrix;
846         int loc_PixelToScreenTexCoord;
847         int loc_ModelToReflectCube;
848         int loc_ShadowMapMatrix;
849         int loc_BloomColorSubtract;
850         int loc_NormalmapScrollBlend;
851         int loc_BounceGridMatrix;
852         int loc_BounceGridIntensity;
853 }
854 r_glsl_permutation_t;
855
856 #define SHADERPERMUTATION_HASHSIZE 256
857
858
859 // non-degradable "lightweight" shader parameters to keep the permutations simpler
860 // these can NOT degrade! only use for simple stuff
861 enum
862 {
863         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
864         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
865         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
866         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
867         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
868         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
869         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
870 };
871 #define SHADERSTATICPARMS_COUNT 7
872
873 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
874 static int shaderstaticparms_count = 0;
875
876 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
877 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
878 qboolean R_CompileShader_CheckStaticParms(void)
879 {
880         static int r_compileshader_staticparms_save[1];
881         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
882         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
883
884         // detect all
885         if (r_glsl_saturation_redcompensate.integer)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
887         if (r_glsl_vertextextureblend_usebothalphas.integer)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
889         if (r_shadow_glossexact.integer)
890                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
891         if (r_glsl_postprocess.integer)
892         {
893                 if (r_glsl_postprocess_uservec1_enable.integer)
894                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
895                 if (r_glsl_postprocess_uservec2_enable.integer)
896                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
897                 if (r_glsl_postprocess_uservec3_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
899                 if (r_glsl_postprocess_uservec4_enable.integer)
900                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
901         }
902         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
903 }
904
905 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
906         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
907                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
908         else \
909                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
910 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
911 {
912         shaderstaticparms_count = 0;
913
914         // emit all
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
922 }
923
924 /// information about each possible shader permutation
925 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
926 /// currently selected permutation
927 r_glsl_permutation_t *r_glsl_permutation;
928 /// storage for permutations linked in the hash table
929 memexpandablearray_t r_glsl_permutationarray;
930
931 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
932 {
933         //unsigned int hashdepth = 0;
934         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
935         r_glsl_permutation_t *p;
936         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
937         {
938                 if (p->mode == mode && p->permutation == permutation)
939                 {
940                         //if (hashdepth > 10)
941                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
942                         return p;
943                 }
944                 //hashdepth++;
945         }
946         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
947         p->mode = mode;
948         p->permutation = permutation;
949         p->hashnext = r_glsl_permutationhash[mode][hashindex];
950         r_glsl_permutationhash[mode][hashindex] = p;
951         //if (hashdepth > 10)
952         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
953         return p;
954 }
955
956 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
957 {
958         char *shaderstring;
959         if (!filename || !filename[0])
960                 return NULL;
961         if (!strcmp(filename, "glsl/default.glsl"))
962         {
963                 if (!glslshaderstring)
964                 {
965                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
966                         if (glslshaderstring)
967                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
968                         else
969                                 glslshaderstring = (char *)builtinshaderstring;
970                 }
971                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
972                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
973                 return shaderstring;
974         }
975         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
976         if (shaderstring)
977         {
978                 if (printfromdisknotice)
979                         Con_DPrintf("from disk %s... ", filename);
980                 return shaderstring;
981         }
982         return shaderstring;
983 }
984
985 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
986 {
987         int i;
988         int sampler;
989         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
990         char *vertexstring, *geometrystring, *fragmentstring;
991         char permutationname[256];
992         int vertstrings_count = 0;
993         int geomstrings_count = 0;
994         int fragstrings_count = 0;
995         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
997         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
998
999         if (p->compiled)
1000                 return;
1001         p->compiled = true;
1002         p->program = 0;
1003
1004         permutationname[0] = 0;
1005         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1006         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1007         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1008
1009         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1010
1011         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1012         if(vid.support.gl20shaders130)
1013         {
1014                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1015                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1016                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1017                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1018                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1019                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1020         }
1021
1022         // the first pretext is which type of shader to compile as
1023         // (later these will all be bound together as a program object)
1024         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1025         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1026         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1027
1028         // the second pretext is the mode (for example a light source)
1029         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1030         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1031         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1032         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1033
1034         // now add all the permutation pretexts
1035         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1036         {
1037                 if (permutation & (1<<i))
1038                 {
1039                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1040                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1041                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1042                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1043                 }
1044                 else
1045                 {
1046                         // keep line numbers correct
1047                         vertstrings_list[vertstrings_count++] = "\n";
1048                         geomstrings_list[geomstrings_count++] = "\n";
1049                         fragstrings_list[fragstrings_count++] = "\n";
1050                 }
1051         }
1052
1053         // add static parms
1054         R_CompileShader_AddStaticParms(mode, permutation);
1055         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056         vertstrings_count += shaderstaticparms_count;
1057         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058         geomstrings_count += shaderstaticparms_count;
1059         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1060         fragstrings_count += shaderstaticparms_count;
1061
1062         // now append the shader text itself
1063         vertstrings_list[vertstrings_count++] = vertexstring;
1064         geomstrings_list[geomstrings_count++] = geometrystring;
1065         fragstrings_list[fragstrings_count++] = fragmentstring;
1066
1067         // if any sources were NULL, clear the respective list
1068         if (!vertexstring)
1069                 vertstrings_count = 0;
1070         if (!geometrystring)
1071                 geomstrings_count = 0;
1072         if (!fragmentstring)
1073                 fragstrings_count = 0;
1074
1075         // compile the shader program
1076         if (vertstrings_count + geomstrings_count + fragstrings_count)
1077                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1078         if (p->program)
1079         {
1080                 CHECKGLERROR
1081                 qglUseProgram(p->program);CHECKGLERROR
1082                 // look up all the uniform variable names we care about, so we don't
1083                 // have to look them up every time we set them
1084
1085                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1086                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1087                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1088                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1089                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1090                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1091                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1092                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1093                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1094                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1095                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1096                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1097                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1098                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1099                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1100                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1101                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1102                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1103                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1104                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1105                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1106                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1107                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1108                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1109                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1110                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1111                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1112                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1113                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1114                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1115                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1116                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1117                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1118                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1119                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1120                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1121                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1122                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1123                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1124                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1125                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1126                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1127                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1128                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1129                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1130                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1131                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1132                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1133                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1134                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1135                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1136                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1137                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1138                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1139                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1140                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1141                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1142                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1143                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1144                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1145                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1146                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1147                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1148                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1149                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1150                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1151                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1152                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1153                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1154                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1155                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1156                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1157                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1158                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1159                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1160                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1161                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1162                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1163                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1164                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1165                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1166                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1167                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1168                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1169                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1170                 // initialize the samplers to refer to the texture units we use
1171                 p->tex_Texture_First = -1;
1172                 p->tex_Texture_Second = -1;
1173                 p->tex_Texture_GammaRamps = -1;
1174                 p->tex_Texture_Normal = -1;
1175                 p->tex_Texture_Color = -1;
1176                 p->tex_Texture_Gloss = -1;
1177                 p->tex_Texture_Glow = -1;
1178                 p->tex_Texture_SecondaryNormal = -1;
1179                 p->tex_Texture_SecondaryColor = -1;
1180                 p->tex_Texture_SecondaryGloss = -1;
1181                 p->tex_Texture_SecondaryGlow = -1;
1182                 p->tex_Texture_Pants = -1;
1183                 p->tex_Texture_Shirt = -1;
1184                 p->tex_Texture_FogHeightTexture = -1;
1185                 p->tex_Texture_FogMask = -1;
1186                 p->tex_Texture_Lightmap = -1;
1187                 p->tex_Texture_Deluxemap = -1;
1188                 p->tex_Texture_Attenuation = -1;
1189                 p->tex_Texture_Cube = -1;
1190                 p->tex_Texture_Refraction = -1;
1191                 p->tex_Texture_Reflection = -1;
1192                 p->tex_Texture_ShadowMap2D = -1;
1193                 p->tex_Texture_CubeProjection = -1;
1194                 p->tex_Texture_ScreenDepth = -1;
1195                 p->tex_Texture_ScreenNormalMap = -1;
1196                 p->tex_Texture_ScreenDiffuse = -1;
1197                 p->tex_Texture_ScreenSpecular = -1;
1198                 p->tex_Texture_ReflectMask = -1;
1199                 p->tex_Texture_ReflectCube = -1;
1200                 p->tex_Texture_BounceGrid = -1;
1201                 sampler = 0;
1202                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1203                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1204                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1205                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1206                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1207                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1208                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1209                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1210                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1211                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1212                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1213                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1214                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1215                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1216                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1217                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1218                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1219                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1220                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1221                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1222                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1223                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1224                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1225                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1226                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1227                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1228                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1229                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1230                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1231                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1232                 CHECKGLERROR
1233                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1234         }
1235         else
1236                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1237
1238         // free the strings
1239         if (vertexstring)
1240                 Mem_Free(vertexstring);
1241         if (geometrystring)
1242                 Mem_Free(geometrystring);
1243         if (fragmentstring)
1244                 Mem_Free(fragmentstring);
1245 }
1246
1247 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1248 {
1249         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1250         if (r_glsl_permutation != perm)
1251         {
1252                 r_glsl_permutation = perm;
1253                 if (!r_glsl_permutation->program)
1254                 {
1255                         if (!r_glsl_permutation->compiled)
1256                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1257                         if (!r_glsl_permutation->program)
1258                         {
1259                                 // remove features until we find a valid permutation
1260                                 int i;
1261                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1262                                 {
1263                                         // reduce i more quickly whenever it would not remove any bits
1264                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1265                                         if (!(permutation & j))
1266                                                 continue;
1267                                         permutation -= j;
1268                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1269                                         if (!r_glsl_permutation->compiled)
1270                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1271                                         if (r_glsl_permutation->program)
1272                                                 break;
1273                                 }
1274                                 if (i >= SHADERPERMUTATION_COUNT)
1275                                 {
1276                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1277                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1278                                         qglUseProgram(0);CHECKGLERROR
1279                                         return; // no bit left to clear, entire mode is broken
1280                                 }
1281                         }
1282                 }
1283                 CHECKGLERROR
1284                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1285         }
1286         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1287         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1288         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1289 }
1290
1291 #ifdef SUPPORTD3D
1292
1293 #ifdef SUPPORTD3D
1294 #include <d3d9.h>
1295 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1296 extern D3DCAPS9 vid_d3d9caps;
1297 #endif
1298
1299 struct r_hlsl_permutation_s;
1300 typedef struct r_hlsl_permutation_s
1301 {
1302         /// hash lookup data
1303         struct r_hlsl_permutation_s *hashnext;
1304         unsigned int mode;
1305         unsigned int permutation;
1306
1307         /// indicates if we have tried compiling this permutation already
1308         qboolean compiled;
1309         /// NULL if compilation failed
1310         IDirect3DVertexShader9 *vertexshader;
1311         IDirect3DPixelShader9 *pixelshader;
1312 }
1313 r_hlsl_permutation_t;
1314
1315 typedef enum D3DVSREGISTER_e
1316 {
1317         D3DVSREGISTER_TexMatrix = 0, // float4x4
1318         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1319         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1320         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1321         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1322         D3DVSREGISTER_ModelToLight = 20, // float4x4
1323         D3DVSREGISTER_EyePosition = 24,
1324         D3DVSREGISTER_FogPlane = 25,
1325         D3DVSREGISTER_LightDir = 26,
1326         D3DVSREGISTER_LightPosition = 27,
1327 }
1328 D3DVSREGISTER_t;
1329
1330 typedef enum D3DPSREGISTER_e
1331 {
1332         D3DPSREGISTER_Alpha = 0,
1333         D3DPSREGISTER_BloomBlur_Parameters = 1,
1334         D3DPSREGISTER_ClientTime = 2,
1335         D3DPSREGISTER_Color_Ambient = 3,
1336         D3DPSREGISTER_Color_Diffuse = 4,
1337         D3DPSREGISTER_Color_Specular = 5,
1338         D3DPSREGISTER_Color_Glow = 6,
1339         D3DPSREGISTER_Color_Pants = 7,
1340         D3DPSREGISTER_Color_Shirt = 8,
1341         D3DPSREGISTER_DeferredColor_Ambient = 9,
1342         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1343         D3DPSREGISTER_DeferredColor_Specular = 11,
1344         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1345         D3DPSREGISTER_DeferredMod_Specular = 13,
1346         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1347         D3DPSREGISTER_EyePosition = 15, // unused
1348         D3DPSREGISTER_FogColor = 16,
1349         D3DPSREGISTER_FogHeightFade = 17,
1350         D3DPSREGISTER_FogPlane = 18,
1351         D3DPSREGISTER_FogPlaneViewDist = 19,
1352         D3DPSREGISTER_FogRangeRecip = 20,
1353         D3DPSREGISTER_LightColor = 21,
1354         D3DPSREGISTER_LightDir = 22, // unused
1355         D3DPSREGISTER_LightPosition = 23,
1356         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1357         D3DPSREGISTER_PixelSize = 25,
1358         D3DPSREGISTER_ReflectColor = 26,
1359         D3DPSREGISTER_ReflectFactor = 27,
1360         D3DPSREGISTER_ReflectOffset = 28,
1361         D3DPSREGISTER_RefractColor = 29,
1362         D3DPSREGISTER_Saturation = 30,
1363         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1364         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1365         D3DPSREGISTER_ScreenToDepth = 33,
1366         D3DPSREGISTER_ShadowMap_Parameters = 34,
1367         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1368         D3DPSREGISTER_SpecularPower = 36,
1369         D3DPSREGISTER_UserVec1 = 37,
1370         D3DPSREGISTER_UserVec2 = 38,
1371         D3DPSREGISTER_UserVec3 = 39,
1372         D3DPSREGISTER_UserVec4 = 40,
1373         D3DPSREGISTER_ViewTintColor = 41,
1374         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1375         D3DPSREGISTER_BloomColorSubtract = 43,
1376         D3DPSREGISTER_ViewToLight = 44, // float4x4
1377         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1378         D3DPSREGISTER_NormalmapScrollBlend = 52,
1379         // next at 53
1380 }
1381 D3DPSREGISTER_t;
1382
1383 /// information about each possible shader permutation
1384 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1385 /// currently selected permutation
1386 r_hlsl_permutation_t *r_hlsl_permutation;
1387 /// storage for permutations linked in the hash table
1388 memexpandablearray_t r_hlsl_permutationarray;
1389
1390 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1391 {
1392         //unsigned int hashdepth = 0;
1393         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1394         r_hlsl_permutation_t *p;
1395         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1396         {
1397                 if (p->mode == mode && p->permutation == permutation)
1398                 {
1399                         //if (hashdepth > 10)
1400                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1401                         return p;
1402                 }
1403                 //hashdepth++;
1404         }
1405         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1406         p->mode = mode;
1407         p->permutation = permutation;
1408         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1409         r_hlsl_permutationhash[mode][hashindex] = p;
1410         //if (hashdepth > 10)
1411         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1412         return p;
1413 }
1414
1415 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1416 {
1417         char *shaderstring;
1418         if (!filename || !filename[0])
1419                 return NULL;
1420         if (!strcmp(filename, "hlsl/default.hlsl"))
1421         {
1422                 if (!hlslshaderstring)
1423                 {
1424                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1425                         if (hlslshaderstring)
1426                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1427                         else
1428                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1429                 }
1430                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1431                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1432                 return shaderstring;
1433         }
1434         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1435         if (shaderstring)
1436         {
1437                 if (printfromdisknotice)
1438                         Con_DPrintf("from disk %s... ", filename);
1439                 return shaderstring;
1440         }
1441         return shaderstring;
1442 }
1443
1444 #include <d3dx9.h>
1445 //#include <d3dx9shader.h>
1446 //#include <d3dx9mesh.h>
1447
1448 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1449 {
1450         DWORD *vsbin = NULL;
1451         DWORD *psbin = NULL;
1452         fs_offset_t vsbinsize;
1453         fs_offset_t psbinsize;
1454 //      IDirect3DVertexShader9 *vs = NULL;
1455 //      IDirect3DPixelShader9 *ps = NULL;
1456         ID3DXBuffer *vslog = NULL;
1457         ID3DXBuffer *vsbuffer = NULL;
1458         ID3DXConstantTable *vsconstanttable = NULL;
1459         ID3DXBuffer *pslog = NULL;
1460         ID3DXBuffer *psbuffer = NULL;
1461         ID3DXConstantTable *psconstanttable = NULL;
1462         int vsresult = 0;
1463         int psresult = 0;
1464         char temp[MAX_INPUTLINE];
1465         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1466         qboolean debugshader = gl_paranoid.integer != 0;
1467         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1468         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1469         if (!debugshader)
1470         {
1471                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1472                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1473         }
1474         if ((!vsbin && vertstring) || (!psbin && fragstring))
1475         {
1476                 const char* dllnames_d3dx9 [] =
1477                 {
1478                         "d3dx9_43.dll",
1479                         "d3dx9_42.dll",
1480                         "d3dx9_41.dll",
1481                         "d3dx9_40.dll",
1482                         "d3dx9_39.dll",
1483                         "d3dx9_38.dll",
1484                         "d3dx9_37.dll",
1485                         "d3dx9_36.dll",
1486                         "d3dx9_35.dll",
1487                         "d3dx9_34.dll",
1488                         "d3dx9_33.dll",
1489                         "d3dx9_32.dll",
1490                         "d3dx9_31.dll",
1491                         "d3dx9_30.dll",
1492                         "d3dx9_29.dll",
1493                         "d3dx9_28.dll",
1494                         "d3dx9_27.dll",
1495                         "d3dx9_26.dll",
1496                         "d3dx9_25.dll",
1497                         "d3dx9_24.dll",
1498                         NULL
1499                 };
1500                 dllhandle_t d3dx9_dll = NULL;
1501                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1503                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1504                 dllfunction_t d3dx9_dllfuncs[] =
1505                 {
1506                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1507                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1508                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1509                         {NULL, NULL}
1510                 };
1511                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1512                 {
1513                         DWORD shaderflags = 0;
1514                         if (debugshader)
1515                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1516                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1517                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1518                         if (vertstring && vertstring[0])
1519                         {
1520                                 if (debugshader)
1521                                 {
1522 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1523 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1524                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1525                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1526                                 }
1527                                 else
1528                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1529                                 if (vsbuffer)
1530                                 {
1531                                         vsbinsize = vsbuffer->GetBufferSize();
1532                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1533                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1534                                         vsbuffer->Release();
1535                                 }
1536                                 if (vslog)
1537                                 {
1538                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1539                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1540                                         vslog->Release();
1541                                 }
1542                         }
1543                         if (fragstring && fragstring[0])
1544                         {
1545                                 if (debugshader)
1546                                 {
1547 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1548 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1549                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1550                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1551                                 }
1552                                 else
1553                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1554                                 if (psbuffer)
1555                                 {
1556                                         psbinsize = psbuffer->GetBufferSize();
1557                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1558                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1559                                         psbuffer->Release();
1560                                 }
1561                                 if (pslog)
1562                                 {
1563                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1564                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1565                                         pslog->Release();
1566                                 }
1567                         }
1568                         Sys_UnloadLibrary(&d3dx9_dll);
1569                 }
1570                 else
1571                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1572         }
1573         if (vsbin && psbin)
1574         {
1575                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1576                 if (FAILED(vsresult))
1577                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1578                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1579                 if (FAILED(psresult))
1580                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1581         }
1582         // free the shader data
1583         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1584         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1585 }
1586
1587 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1588 {
1589         int i;
1590         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1591         int vertstring_length = 0;
1592         int geomstring_length = 0;
1593         int fragstring_length = 0;
1594         char *t;
1595         char *vertexstring, *geometrystring, *fragmentstring;
1596         char *vertstring, *geomstring, *fragstring;
1597         char permutationname[256];
1598         char cachename[256];
1599         int vertstrings_count = 0;
1600         int geomstrings_count = 0;
1601         int fragstrings_count = 0;
1602         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1604         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1605
1606         if (p->compiled)
1607                 return;
1608         p->compiled = true;
1609         p->vertexshader = NULL;
1610         p->pixelshader = NULL;
1611
1612         permutationname[0] = 0;
1613         cachename[0] = 0;
1614         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1615         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1616         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1617
1618         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1619         strlcat(cachename, "hlsl/", sizeof(cachename));
1620
1621         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1622         vertstrings_count = 0;
1623         geomstrings_count = 0;
1624         fragstrings_count = 0;
1625         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1626         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1627         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1628
1629         // the first pretext is which type of shader to compile as
1630         // (later these will all be bound together as a program object)
1631         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1632         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1633         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1634
1635         // the second pretext is the mode (for example a light source)
1636         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1637         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1638         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1639         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1640         strlcat(cachename, modeinfo->name, sizeof(cachename));
1641
1642         // now add all the permutation pretexts
1643         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1644         {
1645                 if (permutation & (1<<i))
1646                 {
1647                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1648                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1649                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1650                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1651                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1652                 }
1653                 else
1654                 {
1655                         // keep line numbers correct
1656                         vertstrings_list[vertstrings_count++] = "\n";
1657                         geomstrings_list[geomstrings_count++] = "\n";
1658                         fragstrings_list[fragstrings_count++] = "\n";
1659                 }
1660         }
1661
1662         // add static parms
1663         R_CompileShader_AddStaticParms(mode, permutation);
1664         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665         vertstrings_count += shaderstaticparms_count;
1666         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667         geomstrings_count += shaderstaticparms_count;
1668         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1669         fragstrings_count += shaderstaticparms_count;
1670
1671         // replace spaces in the cachename with _ characters
1672         for (i = 0;cachename[i];i++)
1673                 if (cachename[i] == ' ')
1674                         cachename[i] = '_';
1675
1676         // now append the shader text itself
1677         vertstrings_list[vertstrings_count++] = vertexstring;
1678         geomstrings_list[geomstrings_count++] = geometrystring;
1679         fragstrings_list[fragstrings_count++] = fragmentstring;
1680
1681         // if any sources were NULL, clear the respective list
1682         if (!vertexstring)
1683                 vertstrings_count = 0;
1684         if (!geometrystring)
1685                 geomstrings_count = 0;
1686         if (!fragmentstring)
1687                 fragstrings_count = 0;
1688
1689         vertstring_length = 0;
1690         for (i = 0;i < vertstrings_count;i++)
1691                 vertstring_length += strlen(vertstrings_list[i]);
1692         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1693         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1694                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1695
1696         geomstring_length = 0;
1697         for (i = 0;i < geomstrings_count;i++)
1698                 geomstring_length += strlen(geomstrings_list[i]);
1699         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1700         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1701                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1702
1703         fragstring_length = 0;
1704         for (i = 0;i < fragstrings_count;i++)
1705                 fragstring_length += strlen(fragstrings_list[i]);
1706         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1707         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1708                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1709
1710         // try to load the cached shader, or generate one
1711         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1712
1713         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1714                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1715         else
1716                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1717
1718         // free the strings
1719         if (vertstring)
1720                 Mem_Free(vertstring);
1721         if (geomstring)
1722                 Mem_Free(geomstring);
1723         if (fragstring)
1724                 Mem_Free(fragstring);
1725         if (vertexstring)
1726                 Mem_Free(vertexstring);
1727         if (geometrystring)
1728                 Mem_Free(geometrystring);
1729         if (fragmentstring)
1730                 Mem_Free(fragmentstring);
1731 }
1732
1733 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1734 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1735 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);}
1736 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);}
1737 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);}
1738 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);}
1739
1740 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1741 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1742 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);}
1743 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);}
1744 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);}
1745 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);}
1746
1747 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1748 {
1749         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1750         if (r_hlsl_permutation != perm)
1751         {
1752                 r_hlsl_permutation = perm;
1753                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1754                 {
1755                         if (!r_hlsl_permutation->compiled)
1756                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1757                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1758                         {
1759                                 // remove features until we find a valid permutation
1760                                 int i;
1761                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1762                                 {
1763                                         // reduce i more quickly whenever it would not remove any bits
1764                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1765                                         if (!(permutation & j))
1766                                                 continue;
1767                                         permutation -= j;
1768                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1769                                         if (!r_hlsl_permutation->compiled)
1770                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1771                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1772                                                 break;
1773                                 }
1774                                 if (i >= SHADERPERMUTATION_COUNT)
1775                                 {
1776                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1777                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1778                                         return; // no bit left to clear, entire mode is broken
1779                                 }
1780                         }
1781                 }
1782                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1783                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1784         }
1785         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1786         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1787         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1788 }
1789 #endif
1790
1791 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1792 {
1793         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1794         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1795         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1796         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1797 }
1798
1799 void R_GLSL_Restart_f(void)
1800 {
1801         unsigned int i, limit;
1802         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1803                 Mem_Free(glslshaderstring);
1804         glslshaderstring = NULL;
1805         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1806                 Mem_Free(hlslshaderstring);
1807         hlslshaderstring = NULL;
1808         switch(vid.renderpath)
1809         {
1810         case RENDERPATH_D3D9:
1811 #ifdef SUPPORTD3D
1812                 {
1813                         r_hlsl_permutation_t *p;
1814                         r_hlsl_permutation = NULL;
1815                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1816                         for (i = 0;i < limit;i++)
1817                         {
1818                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1819                                 {
1820                                         if (p->vertexshader)
1821                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1822                                         if (p->pixelshader)
1823                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1824                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1825                                 }
1826                         }
1827                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1828                 }
1829 #endif
1830                 break;
1831         case RENDERPATH_D3D10:
1832                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1833                 break;
1834         case RENDERPATH_D3D11:
1835                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1836                 break;
1837         case RENDERPATH_GL20:
1838         case RENDERPATH_GLES2:
1839                 {
1840                         r_glsl_permutation_t *p;
1841                         r_glsl_permutation = NULL;
1842                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1843                         for (i = 0;i < limit;i++)
1844                         {
1845                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1846                                 {
1847                                         GL_Backend_FreeProgram(p->program);
1848                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1849                                 }
1850                         }
1851                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1852                 }
1853                 break;
1854         case RENDERPATH_GL13:
1855         case RENDERPATH_GL11:
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                 R_Mesh_TexBind(0, first );
1929                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1930                 R_Mesh_TexBind(1, second);
1931                 if (second)
1932                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1933                 break;
1934         case RENDERPATH_GL11:
1935                 R_Mesh_TexBind(0, first );
1936                 break;
1937         case RENDERPATH_SOFT:
1938                 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))));
1939                 R_Mesh_TexBind(GL20TU_FIRST , first );
1940                 R_Mesh_TexBind(GL20TU_SECOND, second);
1941                 break;
1942         }
1943 }
1944
1945 void R_SetupShader_DepthOrShadow(void)
1946 {
1947         switch (vid.renderpath)
1948         {
1949         case RENDERPATH_D3D9:
1950 #ifdef SUPPORTD3D
1951                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1952 #endif
1953                 break;
1954         case RENDERPATH_D3D10:
1955                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1956                 break;
1957         case RENDERPATH_D3D11:
1958                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1959                 break;
1960         case RENDERPATH_GL20:
1961         case RENDERPATH_GLES2:
1962                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1963                 break;
1964         case RENDERPATH_GL13:
1965                 R_Mesh_TexBind(0, 0);
1966                 R_Mesh_TexBind(1, 0);
1967                 break;
1968         case RENDERPATH_GL11:
1969                 R_Mesh_TexBind(0, 0);
1970                 break;
1971         case RENDERPATH_SOFT:
1972                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1973                 break;
1974         }
1975 }
1976
1977 void R_SetupShader_ShowDepth(void)
1978 {
1979         switch (vid.renderpath)
1980         {
1981         case RENDERPATH_D3D9:
1982 #ifdef SUPPORTHLSL
1983                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1984 #endif
1985                 break;
1986         case RENDERPATH_D3D10:
1987                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1988                 break;
1989         case RENDERPATH_D3D11:
1990                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1991                 break;
1992         case RENDERPATH_GL20:
1993         case RENDERPATH_GLES2:
1994                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1995                 break;
1996         case RENDERPATH_GL13:
1997                 break;
1998         case RENDERPATH_GL11:
1999                 break;
2000         case RENDERPATH_SOFT:
2001                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2002                 break;
2003         }
2004 }
2005
2006 extern qboolean r_shadow_usingdeferredprepass;
2007 extern cvar_t r_shadow_deferred_8bitrange;
2008 extern rtexture_t *r_shadow_attenuationgradienttexture;
2009 extern rtexture_t *r_shadow_attenuation2dtexture;
2010 extern rtexture_t *r_shadow_attenuation3dtexture;
2011 extern qboolean r_shadow_usingshadowmap2d;
2012 extern qboolean r_shadow_usingshadowmaportho;
2013 extern float r_shadow_shadowmap_texturescale[2];
2014 extern float r_shadow_shadowmap_parameters[4];
2015 extern qboolean r_shadow_shadowmapvsdct;
2016 extern qboolean r_shadow_shadowmapsampler;
2017 extern int r_shadow_shadowmappcf;
2018 extern rtexture_t *r_shadow_shadowmap2dtexture;
2019 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2020 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2021 extern matrix4x4_t r_shadow_shadowmapmatrix;
2022 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2023 extern int r_shadow_prepass_width;
2024 extern int r_shadow_prepass_height;
2025 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2026 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2027 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2028 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2029 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2030
2031 #define BLENDFUNC_ALLOWS_COLORMOD      1
2032 #define BLENDFUNC_ALLOWS_FOG           2
2033 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2034 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2035 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2036 static int R_BlendFuncFlags(int src, int dst)
2037 {
2038         int r = 0;
2039
2040         // a blendfunc allows colormod if:
2041         // a) it can never keep the destination pixel invariant, or
2042         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2043         // this is to prevent unintended side effects from colormod
2044
2045         // a blendfunc allows fog if:
2046         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2047         // this is to prevent unintended side effects from fog
2048
2049         // these checks are the output of fogeval.pl
2050
2051         r |= BLENDFUNC_ALLOWS_COLORMOD;
2052         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2053         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2054         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2055         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2056         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2057         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2058         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2059         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2060         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2061         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2062         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2063         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2064         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2065         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2066         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2067         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2068         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2069         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2070         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2071         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2072         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2073
2074         return r;
2075 }
2076
2077 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)
2078 {
2079         // select a permutation of the lighting shader appropriate to this
2080         // combination of texture, entity, light source, and fogging, only use the
2081         // minimum features necessary to avoid wasting rendering time in the
2082         // fragment shader on features that are not being used
2083         unsigned int permutation = 0;
2084         unsigned int mode = 0;
2085         int blendfuncflags;
2086         static float dummy_colormod[3] = {1, 1, 1};
2087         float *colormod = rsurface.colormod;
2088         float m16f[16];
2089         matrix4x4_t tempmatrix;
2090         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2091         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2092                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2093         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2094                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2095         if (rsurfacepass == RSURFPASS_BACKGROUND)
2096         {
2097                 // distorted background
2098                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2099                 {
2100                         mode = SHADERMODE_WATER;
2101                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2102                         {
2103                                 // this is the right thing to do for wateralpha
2104                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2105                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2106                         }
2107                         else
2108                         {
2109                                 // this is the right thing to do for entity alpha
2110                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2111                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2112                         }
2113                 }
2114                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2115                 {
2116                         mode = SHADERMODE_REFRACTION;
2117                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2118                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2119                 }
2120                 else
2121                 {
2122                         mode = SHADERMODE_GENERIC;
2123                         permutation |= SHADERPERMUTATION_DIFFUSE;
2124                         GL_BlendFunc(GL_ONE, GL_ZERO);
2125                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2126                 }
2127         }
2128         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2129         {
2130                 if (r_glsl_offsetmapping.integer)
2131                 {
2132                         switch(rsurface.texture->offsetmapping)
2133                         {
2134                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2135                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2136                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2137                         case OFFSETMAPPING_OFF: break;
2138                         }
2139                 }
2140                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2141                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2142                 // normalmap (deferred prepass), may use alpha test on diffuse
2143                 mode = SHADERMODE_DEFERREDGEOMETRY;
2144                 GL_BlendFunc(GL_ONE, GL_ZERO);
2145                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2146         }
2147         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2148         {
2149                 if (r_glsl_offsetmapping.integer)
2150                 {
2151                         switch(rsurface.texture->offsetmapping)
2152                         {
2153                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2154                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2155                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2156                         case OFFSETMAPPING_OFF: break;
2157                         }
2158                 }
2159                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2160                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2161                 // light source
2162                 mode = SHADERMODE_LIGHTSOURCE;
2163                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2164                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2165                 if (diffusescale > 0)
2166                         permutation |= SHADERPERMUTATION_DIFFUSE;
2167                 if (specularscale > 0)
2168                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2169                 if (r_refdef.fogenabled)
2170                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2171                 if (rsurface.texture->colormapping)
2172                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2173                 if (r_shadow_usingshadowmap2d)
2174                 {
2175                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2176                         if(r_shadow_shadowmapvsdct)
2177                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2178
2179                         if (r_shadow_shadowmapsampler)
2180                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2181                         if (r_shadow_shadowmappcf > 1)
2182                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2183                         else if (r_shadow_shadowmappcf)
2184                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2185                 }
2186                 if (rsurface.texture->reflectmasktexture)
2187                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2188                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2189                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2190         }
2191         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2192         {
2193                 if (r_glsl_offsetmapping.integer)
2194                 {
2195                         switch(rsurface.texture->offsetmapping)
2196                         {
2197                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2198                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2199                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2200                         case OFFSETMAPPING_OFF: break;
2201                         }
2202                 }
2203                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2204                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2205                 // unshaded geometry (fullbright or ambient model lighting)
2206                 mode = SHADERMODE_FLATCOLOR;
2207                 ambientscale = diffusescale = specularscale = 0;
2208                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2209                         permutation |= SHADERPERMUTATION_GLOW;
2210                 if (r_refdef.fogenabled)
2211                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2212                 if (rsurface.texture->colormapping)
2213                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2214                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2215                 {
2216                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2217                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2218
2219                         if (r_shadow_shadowmapsampler)
2220                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2221                         if (r_shadow_shadowmappcf > 1)
2222                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2223                         else if (r_shadow_shadowmappcf)
2224                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2225                 }
2226                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2227                         permutation |= SHADERPERMUTATION_REFLECTION;
2228                 if (rsurface.texture->reflectmasktexture)
2229                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2230                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2231                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2232         }
2233         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2234         {
2235                 if (r_glsl_offsetmapping.integer)
2236                 {
2237                         switch(rsurface.texture->offsetmapping)
2238                         {
2239                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2240                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2241                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2242                         case OFFSETMAPPING_OFF: break;
2243                         }
2244                 }
2245                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2246                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2247                 // directional model lighting
2248                 mode = SHADERMODE_LIGHTDIRECTION;
2249                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2250                         permutation |= SHADERPERMUTATION_GLOW;
2251                 permutation |= SHADERPERMUTATION_DIFFUSE;
2252                 if (specularscale > 0)
2253                         permutation |= SHADERPERMUTATION_SPECULAR;
2254                 if (r_refdef.fogenabled)
2255                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2256                 if (rsurface.texture->colormapping)
2257                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2258                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2259                 {
2260                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2261                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2262
2263                         if (r_shadow_shadowmapsampler)
2264                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2265                         if (r_shadow_shadowmappcf > 1)
2266                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2267                         else if (r_shadow_shadowmappcf)
2268                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2269                 }
2270                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2271                         permutation |= SHADERPERMUTATION_REFLECTION;
2272                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2273                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2274                 if (rsurface.texture->reflectmasktexture)
2275                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2276                 if (r_shadow_bouncegridtexture)
2277                 {
2278                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2279                         if (r_shadow_bouncegriddirectional)
2280                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2281                 }
2282                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2283                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2284         }
2285         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2286         {
2287                 if (r_glsl_offsetmapping.integer)
2288                 {
2289                         switch(rsurface.texture->offsetmapping)
2290                         {
2291                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2292                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2293                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2294                         case OFFSETMAPPING_OFF: break;
2295                         }
2296                 }
2297                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2298                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2299                 // ambient model lighting
2300                 mode = SHADERMODE_LIGHTDIRECTION;
2301                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2302                         permutation |= SHADERPERMUTATION_GLOW;
2303                 if (r_refdef.fogenabled)
2304                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2305                 if (rsurface.texture->colormapping)
2306                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2307                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2308                 {
2309                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2310                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2311
2312                         if (r_shadow_shadowmapsampler)
2313                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2314                         if (r_shadow_shadowmappcf > 1)
2315                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2316                         else if (r_shadow_shadowmappcf)
2317                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2318                 }
2319                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2320                         permutation |= SHADERPERMUTATION_REFLECTION;
2321                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2322                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2323                 if (rsurface.texture->reflectmasktexture)
2324                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2325                 if (r_shadow_bouncegridtexture)
2326                 {
2327                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2328                         if (r_shadow_bouncegriddirectional)
2329                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2330                 }
2331                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2332                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2333         }
2334         else
2335         {
2336                 if (r_glsl_offsetmapping.integer)
2337                 {
2338                         switch(rsurface.texture->offsetmapping)
2339                         {
2340                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2341                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2342                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2343                         case OFFSETMAPPING_OFF: break;
2344                         }
2345                 }
2346                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2347                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2348                 // lightmapped wall
2349                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2350                         permutation |= SHADERPERMUTATION_GLOW;
2351                 if (r_refdef.fogenabled)
2352                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2353                 if (rsurface.texture->colormapping)
2354                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2355                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2356                 {
2357                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2358                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2359
2360                         if (r_shadow_shadowmapsampler)
2361                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2362                         if (r_shadow_shadowmappcf > 1)
2363                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2364                         else if (r_shadow_shadowmappcf)
2365                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2366                 }
2367                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2368                         permutation |= SHADERPERMUTATION_REFLECTION;
2369                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2370                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2371                 if (rsurface.texture->reflectmasktexture)
2372                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2373                 if (FAKELIGHT_ENABLED)
2374                 {
2375                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2376                         mode = SHADERMODE_FAKELIGHT;
2377                         permutation |= SHADERPERMUTATION_DIFFUSE;
2378                         if (specularscale > 0)
2379                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2380                 }
2381                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2382                 {
2383                         // deluxemapping (light direction texture)
2384                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2385                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2386                         else
2387                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2388                         permutation |= SHADERPERMUTATION_DIFFUSE;
2389                         if (specularscale > 0)
2390                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2391                 }
2392                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2393                 {
2394                         // fake deluxemapping (uniform light direction in tangentspace)
2395                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2396                         permutation |= SHADERPERMUTATION_DIFFUSE;
2397                         if (specularscale > 0)
2398                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2399                 }
2400                 else if (rsurface.uselightmaptexture)
2401                 {
2402                         // ordinary lightmapping (q1bsp, q3bsp)
2403                         mode = SHADERMODE_LIGHTMAP;
2404                 }
2405                 else
2406                 {
2407                         // ordinary vertex coloring (q3bsp)
2408                         mode = SHADERMODE_VERTEXCOLOR;
2409                 }
2410                 if (r_shadow_bouncegridtexture)
2411                 {
2412                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2413                         if (r_shadow_bouncegriddirectional)
2414                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2415                 }
2416                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2417                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2418         }
2419         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2420                 colormod = dummy_colormod;
2421         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2422                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2423         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2424                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2425         switch(vid.renderpath)
2426         {
2427         case RENDERPATH_D3D9:
2428 #ifdef SUPPORTD3D
2429                 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);
2430                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2431                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2432                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2433                 if (mode == SHADERMODE_LIGHTSOURCE)
2434                 {
2435                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2436                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2437                 }
2438                 else
2439                 {
2440                         if (mode == SHADERMODE_LIGHTDIRECTION)
2441                         {
2442                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2443                         }
2444                 }
2445                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2446                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2447                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2448                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2449                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2450
2451                 if (mode == SHADERMODE_LIGHTSOURCE)
2452                 {
2453                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2454                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2455                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2456                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2457                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2458
2459                         // additive passes are only darkened by fog, not tinted
2460                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2461                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2462                 }
2463                 else
2464                 {
2465                         if (mode == SHADERMODE_FLATCOLOR)
2466                         {
2467                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2468                         }
2469                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2470                         {
2471                                 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]);
2472                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2473                                 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);
2474                                 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);
2475                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2476                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2477                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2478                         }
2479                         else
2480                         {
2481                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2482                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2483                                 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);
2484                                 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);
2485                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2486                         }
2487                         // additive passes are only darkened by fog, not tinted
2488                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2489                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2490                         else
2491                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2492                         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);
2493                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2494                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2495                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2496                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2497                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2498                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2499                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2500                         if (mode == SHADERMODE_WATER)
2501                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2502                 }
2503                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2504                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2505                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2506                 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));
2507                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2508                 if (rsurface.texture->pantstexture)
2509                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2510                 else
2511                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2512                 if (rsurface.texture->shirttexture)
2513                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2514                 else
2515                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2516                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2517                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2518                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2519                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2520                 hlslPSSetParameter3f(D3DPSREGISTER_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2521                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2522                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2523
2524                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2525                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2526                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2527                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2528                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2529                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2530                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2531                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2532                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2533                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2534                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2535                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2536                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2537                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2538                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2539                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2540                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2541                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2542                 {
2543                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2544                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2545                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2546                 }
2547                 else
2548                 {
2549                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2550                 }
2551 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2552 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2553                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2554                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2555                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2556                 {
2557                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2558                         if (rsurface.rtlight)
2559                         {
2560                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2561                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2562                         }
2563                 }
2564 #endif
2565                 break;
2566         case RENDERPATH_D3D10:
2567                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2568                 break;
2569         case RENDERPATH_D3D11:
2570                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2571                 break;
2572         case RENDERPATH_GL20:
2573         case RENDERPATH_GLES2:
2574                 if (!vid.useinterleavedarrays)
2575                 {
2576                         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);
2577                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2578                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2579                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2580                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2581                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2582                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2583                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2584                 }
2585                 else
2586                 {
2587                         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);
2588                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2589                 }
2590                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2591                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2592                 if (mode == SHADERMODE_LIGHTSOURCE)
2593                 {
2594                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2595                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2596                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2597                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2598                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2599                         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);
2600         
2601                         // additive passes are only darkened by fog, not tinted
2602                         if (r_glsl_permutation->loc_FogColor >= 0)
2603                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2604                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2605                 }
2606                 else
2607                 {
2608                         if (mode == SHADERMODE_FLATCOLOR)
2609                         {
2610                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2611                         }
2612                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2613                         {
2614                                 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]);
2615                                 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]);
2616                                 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);
2617                                 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);
2618                                 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);
2619                                 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]);
2620                                 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]);
2621                         }
2622                         else
2623                         {
2624                                 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]);
2625                                 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]);
2626                                 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);
2627                                 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);
2628                                 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);
2629                         }
2630                         // additive passes are only darkened by fog, not tinted
2631                         if (r_glsl_permutation->loc_FogColor >= 0)
2632                         {
2633                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2634                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2635                                 else
2636                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2637                         }
2638                         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);
2639                         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]);
2640                         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]);
2641                         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]);
2642                         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]);
2643                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2644                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2645                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2646                         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]);
2647                 }
2648                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2649                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2650                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2651                 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]);
2652                 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]);
2653
2654                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2655                 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));
2656                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2657                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2658                 {
2659                         if (rsurface.texture->pantstexture)
2660                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2661                         else
2662                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2663                 }
2664                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2665                 {
2666                         if (rsurface.texture->shirttexture)
2667                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2668                         else
2669                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2670                 }
2671                 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]);
2672                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2673                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2674                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2675                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform3f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2676                 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]);
2677                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2678                 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);}
2679                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2680
2681                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2682                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2683                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2684                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2685                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2686                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2687                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2688                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2689                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2690                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2691                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2692                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2693                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2694                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2695                 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);
2696                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2697                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2698                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2699                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2700                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2701                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2702                 {
2703                         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);
2704                         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);
2705                         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);
2706                 }
2707                 else
2708                 {
2709                         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);
2710                 }
2711                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2712                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2713                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2714                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2715                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2716                 {
2717                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2718                         if (rsurface.rtlight)
2719                         {
2720                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2721                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2722                         }
2723                 }
2724                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2725                 CHECKGLERROR
2726                 break;
2727         case RENDERPATH_GL13:
2728         case RENDERPATH_GL11:
2729                 break;
2730         case RENDERPATH_SOFT:
2731                 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);
2732                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2733                 R_SetupShader_SetPermutationSoft(mode, permutation);
2734                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2735                 if (mode == SHADERMODE_LIGHTSOURCE)
2736                 {
2737                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2738                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2739                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2740                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2741                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2742                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2743         
2744                         // additive passes are only darkened by fog, not tinted
2745                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2746                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2747                 }
2748                 else
2749                 {
2750                         if (mode == SHADERMODE_FLATCOLOR)
2751                         {
2752                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2753                         }
2754                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2755                         {
2756                                 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]);
2757                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2758                                 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);
2759                                 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);
2760                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2761                                 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]);
2762                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2763                         }
2764                         else
2765                         {
2766                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2767                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2768                                 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);
2769                                 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);
2770                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2771                         }
2772                         // additive passes are only darkened by fog, not tinted
2773                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2774                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2775                         else
2776                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2777                         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);
2778                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2779                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2780                         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]);
2781                         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]);
2782                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2783                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2784                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2785                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2786                 }
2787                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2788                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2789                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2790                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2791                 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]);
2792
2793                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2794                 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));
2795                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2796                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2797                 {
2798                         if (rsurface.texture->pantstexture)
2799                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2800                         else
2801                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2802                 }
2803                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2804                 {
2805                         if (rsurface.texture->shirttexture)
2806                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2807                         else
2808                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2809                 }
2810                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2811                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2812                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2813                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2814                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2815                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2816                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2817
2818                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2819                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2820                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2821                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2822                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2823                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2824                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2825                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2826                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2827                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2828                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2829                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2830                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2831                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2832                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2833                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2834                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2835                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2836                 {
2837                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2838                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2839                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2840                 }
2841                 else
2842                 {
2843                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2844                 }
2845 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2846 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2847                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2848                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2849                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2850                 {
2851                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2852                         if (rsurface.rtlight)
2853                         {
2854                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2855                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2856                         }
2857                 }
2858                 break;
2859         }
2860 }
2861
2862 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2863 {
2864         // select a permutation of the lighting shader appropriate to this
2865         // combination of texture, entity, light source, and fogging, only use the
2866         // minimum features necessary to avoid wasting rendering time in the
2867         // fragment shader on features that are not being used
2868         unsigned int permutation = 0;
2869         unsigned int mode = 0;
2870         const float *lightcolorbase = rtlight->currentcolor;
2871         float ambientscale = rtlight->ambientscale;
2872         float diffusescale = rtlight->diffusescale;
2873         float specularscale = rtlight->specularscale;
2874         // this is the location of the light in view space
2875         vec3_t viewlightorigin;
2876         // this transforms from view space (camera) to light space (cubemap)
2877         matrix4x4_t viewtolight;
2878         matrix4x4_t lighttoview;
2879         float viewtolight16f[16];
2880         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2881         // light source
2882         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2883         if (rtlight->currentcubemap != r_texture_whitecube)
2884                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2885         if (diffusescale > 0)
2886                 permutation |= SHADERPERMUTATION_DIFFUSE;
2887         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2888                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2889         if (r_shadow_usingshadowmap2d)
2890         {
2891                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2892                 if (r_shadow_shadowmapvsdct)
2893                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2894
2895                 if (r_shadow_shadowmapsampler)
2896                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2897                 if (r_shadow_shadowmappcf > 1)
2898                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2899                 else if (r_shadow_shadowmappcf)
2900                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2901         }
2902         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2903         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2904         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2905         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2906         switch(vid.renderpath)
2907         {
2908         case RENDERPATH_D3D9:
2909 #ifdef SUPPORTD3D
2910                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2911                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2912                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2913                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2914                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2915                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2916                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2917                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2918                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2919                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2920                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2921
2922                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2923                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2924                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2925                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2926                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2927                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2928 #endif
2929                 break;
2930         case RENDERPATH_D3D10:
2931                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2932                 break;
2933         case RENDERPATH_D3D11:
2934                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2935                 break;
2936         case RENDERPATH_GL20:
2937         case RENDERPATH_GLES2:
2938                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2939                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2940                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2941                 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);
2942                 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);
2943                 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);
2944                 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]);
2945                 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]);
2946                 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));
2947                 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]);
2948                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2949
2950                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2951                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2952                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2953                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2954                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2955                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2956                 break;
2957         case RENDERPATH_GL13:
2958         case RENDERPATH_GL11:
2959                 break;
2960         case RENDERPATH_SOFT:
2961                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2962                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2963                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2964                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2965                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2966                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2967                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2968                 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]);
2969                 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));
2970                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2971                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2972
2973                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2974                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2975                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2976                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2977                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2978                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2979                 break;
2980         }
2981 }
2982
2983 #define SKINFRAME_HASH 1024
2984
2985 typedef struct
2986 {
2987         int loadsequence; // incremented each level change
2988         memexpandablearray_t array;
2989         skinframe_t *hash[SKINFRAME_HASH];
2990 }
2991 r_skinframe_t;
2992 r_skinframe_t r_skinframe;
2993
2994 void R_SkinFrame_PrepareForPurge(void)
2995 {
2996         r_skinframe.loadsequence++;
2997         // wrap it without hitting zero
2998         if (r_skinframe.loadsequence >= 200)
2999                 r_skinframe.loadsequence = 1;
3000 }
3001
3002 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3003 {
3004         if (!skinframe)
3005                 return;
3006         // mark the skinframe as used for the purging code
3007         skinframe->loadsequence = r_skinframe.loadsequence;
3008 }
3009
3010 void R_SkinFrame_Purge(void)
3011 {
3012         int i;
3013         skinframe_t *s;
3014         for (i = 0;i < SKINFRAME_HASH;i++)
3015         {
3016                 for (s = r_skinframe.hash[i];s;s = s->next)
3017                 {
3018                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3019                         {
3020                                 if (s->merged == s->base)
3021                                         s->merged = NULL;
3022                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3023                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3024                                 R_PurgeTexture(s->merged);s->merged = NULL;
3025                                 R_PurgeTexture(s->base  );s->base   = NULL;
3026                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3027                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3028                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3029                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3030                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3031                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3032                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3033                                 s->loadsequence = 0;
3034                         }
3035                 }
3036         }
3037 }
3038
3039 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3040         skinframe_t *item;
3041         char basename[MAX_QPATH];
3042
3043         Image_StripImageExtension(name, basename, sizeof(basename));
3044
3045         if( last == NULL ) {
3046                 int hashindex;
3047                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3048                 item = r_skinframe.hash[hashindex];
3049         } else {
3050                 item = last->next;
3051         }
3052
3053         // linearly search through the hash bucket
3054         for( ; item ; item = item->next ) {
3055                 if( !strcmp( item->basename, basename ) ) {
3056                         return item;
3057                 }
3058         }
3059         return NULL;
3060 }
3061
3062 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3063 {
3064         skinframe_t *item;
3065         int hashindex;
3066         char basename[MAX_QPATH];
3067
3068         Image_StripImageExtension(name, basename, sizeof(basename));
3069
3070         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3071         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3072                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3073                         break;
3074
3075         if (!item) {
3076                 rtexture_t *dyntexture;
3077                 // check whether its a dynamic texture
3078                 dyntexture = CL_GetDynTexture( basename );
3079                 if (!add && !dyntexture)
3080                         return NULL;
3081                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3082                 memset(item, 0, sizeof(*item));
3083                 strlcpy(item->basename, basename, sizeof(item->basename));
3084                 item->base = dyntexture; // either NULL or dyntexture handle
3085                 item->textureflags = textureflags;
3086                 item->comparewidth = comparewidth;
3087                 item->compareheight = compareheight;
3088                 item->comparecrc = comparecrc;
3089                 item->next = r_skinframe.hash[hashindex];
3090                 r_skinframe.hash[hashindex] = item;
3091         }
3092         else if( item->base == NULL )
3093         {
3094                 rtexture_t *dyntexture;
3095                 // check whether its a dynamic texture
3096                 // 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]
3097                 dyntexture = CL_GetDynTexture( basename );
3098                 item->base = dyntexture; // either NULL or dyntexture handle
3099         }
3100
3101         R_SkinFrame_MarkUsed(item);
3102         return item;
3103 }
3104
3105 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3106         { \
3107                 unsigned long long avgcolor[5], wsum; \
3108                 int pix, comp, w; \
3109                 avgcolor[0] = 0; \
3110                 avgcolor[1] = 0; \
3111                 avgcolor[2] = 0; \
3112                 avgcolor[3] = 0; \
3113                 avgcolor[4] = 0; \
3114                 wsum = 0; \
3115                 for(pix = 0; pix < cnt; ++pix) \
3116                 { \
3117                         w = 0; \
3118                         for(comp = 0; comp < 3; ++comp) \
3119                                 w += getpixel; \
3120                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3121                         { \
3122                                 ++wsum; \
3123                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3124                                 w = getpixel; \
3125                                 for(comp = 0; comp < 3; ++comp) \
3126                                         avgcolor[comp] += getpixel * w; \
3127                                 avgcolor[3] += w; \
3128                         } \
3129                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3130                         avgcolor[4] += getpixel; \
3131                 } \
3132                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3133                         avgcolor[3] = 1; \
3134                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3135                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3136                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3137                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3138         }
3139
3140 extern cvar_t gl_picmip;
3141 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3142 {
3143         int j;
3144         unsigned char *pixels;
3145         unsigned char *bumppixels;
3146         unsigned char *basepixels = NULL;
3147         int basepixels_width = 0;
3148         int basepixels_height = 0;
3149         skinframe_t *skinframe;
3150         rtexture_t *ddsbase = NULL;
3151         qboolean ddshasalpha = false;
3152         float ddsavgcolor[4];
3153         char basename[MAX_QPATH];
3154         int miplevel = R_PicmipForFlags(textureflags);
3155         int savemiplevel = miplevel;
3156         int mymiplevel;
3157
3158         if (cls.state == ca_dedicated)
3159                 return NULL;
3160
3161         // return an existing skinframe if already loaded
3162         // if loading of the first image fails, don't make a new skinframe as it
3163         // would cause all future lookups of this to be missing
3164         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3165         if (skinframe && skinframe->base)
3166                 return skinframe;
3167
3168         Image_StripImageExtension(name, basename, sizeof(basename));
3169
3170         // check for DDS texture file first
3171         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3172         {
3173                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3174                 if (basepixels == NULL)
3175                         return NULL;
3176         }
3177
3178         // FIXME handle miplevel
3179
3180         if (developer_loading.integer)
3181                 Con_Printf("loading skin \"%s\"\n", name);
3182
3183         // we've got some pixels to store, so really allocate this new texture now
3184         if (!skinframe)
3185                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3186         skinframe->stain = NULL;
3187         skinframe->merged = NULL;
3188         skinframe->base = NULL;
3189         skinframe->pants = NULL;
3190         skinframe->shirt = NULL;
3191         skinframe->nmap = NULL;
3192         skinframe->gloss = NULL;
3193         skinframe->glow = NULL;
3194         skinframe->fog = NULL;
3195         skinframe->reflect = NULL;
3196         skinframe->hasalpha = false;
3197
3198         if (ddsbase)
3199         {
3200                 skinframe->base = ddsbase;
3201                 skinframe->hasalpha = ddshasalpha;
3202                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3203                 if (r_loadfog && skinframe->hasalpha)
3204                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3205                 //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]);
3206         }
3207         else
3208         {
3209                 basepixels_width = image_width;
3210                 basepixels_height = image_height;
3211                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3212                 if (textureflags & TEXF_ALPHA)
3213                 {
3214                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3215                         {
3216                                 if (basepixels[j] < 255)
3217                                 {
3218                                         skinframe->hasalpha = true;
3219                                         break;
3220                                 }
3221                         }
3222                         if (r_loadfog && skinframe->hasalpha)
3223                         {
3224                                 // has transparent pixels
3225                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3226                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3227                                 {
3228                                         pixels[j+0] = 255;
3229                                         pixels[j+1] = 255;
3230                                         pixels[j+2] = 255;
3231                                         pixels[j+3] = basepixels[j+3];
3232                                 }
3233                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3234                                 Mem_Free(pixels);
3235                         }
3236                 }
3237                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3238                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3239                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3240                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3241                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3242                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3243         }
3244
3245         if (r_loaddds)
3246         {
3247                 mymiplevel = savemiplevel;
3248                 if (r_loadnormalmap)
3249                         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);
3250                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3251                 if (r_loadgloss)
3252                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3253                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3254                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3255                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3256         }
3257
3258         // _norm is the name used by tenebrae and has been adopted as standard
3259         if (r_loadnormalmap && skinframe->nmap == NULL)
3260         {
3261                 mymiplevel = savemiplevel;
3262                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3263                 {
3264                         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 ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3265                         Mem_Free(pixels);
3266                         pixels = NULL;
3267                 }
3268                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3269                 {
3270                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3271                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3272                         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 ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3273                         Mem_Free(pixels);
3274                         Mem_Free(bumppixels);
3275                 }
3276                 else if (r_shadow_bumpscale_basetexture.value > 0)
3277                 {
3278                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3279                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3280                         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 ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3281                         Mem_Free(pixels);
3282                 }
3283                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3284                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3285         }
3286
3287         // _luma is supported only for tenebrae compatibility
3288         // _glow is the preferred name
3289         mymiplevel = savemiplevel;
3290         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))))
3291         {
3292                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_glow.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3293                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3294                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3295                 Mem_Free(pixels);pixels = NULL;
3296         }
3297
3298         mymiplevel = savemiplevel;
3299         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3300         {
3301                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_gloss.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3302                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3303                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3304                 Mem_Free(pixels);
3305                 pixels = NULL;
3306         }
3307
3308         mymiplevel = savemiplevel;
3309         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3310         {
3311                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3312                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3313                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3314                 Mem_Free(pixels);
3315                 pixels = NULL;
3316         }
3317
3318         mymiplevel = savemiplevel;
3319         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3320         {
3321                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3322                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3323                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3324                 Mem_Free(pixels);
3325                 pixels = NULL;
3326         }
3327
3328         mymiplevel = savemiplevel;
3329         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3330         {
3331                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_reflect.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3332                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3333                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3334                 Mem_Free(pixels);
3335                 pixels = NULL;
3336         }
3337
3338         if (basepixels)
3339                 Mem_Free(basepixels);
3340
3341         return skinframe;
3342 }
3343
3344 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3345 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3346 {
3347         int i;
3348         unsigned char *temp1, *temp2;
3349         skinframe_t *skinframe;
3350
3351         if (cls.state == ca_dedicated)
3352                 return NULL;
3353
3354         // if already loaded just return it, otherwise make a new skinframe
3355         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3356         if (skinframe && skinframe->base)
3357                 return skinframe;
3358
3359         skinframe->stain = NULL;
3360         skinframe->merged = NULL;
3361         skinframe->base = NULL;
3362         skinframe->pants = NULL;
3363         skinframe->shirt = NULL;
3364         skinframe->nmap = NULL;
3365         skinframe->gloss = NULL;
3366         skinframe->glow = NULL;
3367         skinframe->fog = NULL;
3368         skinframe->reflect = NULL;
3369         skinframe->hasalpha = false;
3370
3371         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3372         if (!skindata)
3373                 return NULL;
3374
3375         if (developer_loading.integer)
3376                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3377
3378         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3379         {
3380                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3381                 temp2 = temp1 + width * height * 4;
3382                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3383                 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);
3384                 Mem_Free(temp1);
3385         }
3386         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3387         if (textureflags & TEXF_ALPHA)
3388         {
3389                 for (i = 3;i < width * height * 4;i += 4)
3390                 {
3391                         if (skindata[i] < 255)
3392                         {
3393                                 skinframe->hasalpha = true;
3394                                 break;
3395                         }
3396                 }
3397                 if (r_loadfog && skinframe->hasalpha)
3398                 {
3399                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3400                         memcpy(fogpixels, skindata, width * height * 4);
3401                         for (i = 0;i < width * height * 4;i += 4)
3402                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3403                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3404                         Mem_Free(fogpixels);
3405                 }
3406         }
3407
3408         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3409         //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]);
3410
3411         return skinframe;
3412 }
3413
3414 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3415 {
3416         int i;
3417         int featuresmask;
3418         skinframe_t *skinframe;
3419
3420         if (cls.state == ca_dedicated)
3421                 return NULL;
3422
3423         // if already loaded just return it, otherwise make a new skinframe
3424         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3425         if (skinframe && skinframe->base)
3426                 return skinframe;
3427
3428         skinframe->stain = NULL;
3429         skinframe->merged = NULL;
3430         skinframe->base = NULL;
3431         skinframe->pants = NULL;
3432         skinframe->shirt = NULL;
3433         skinframe->nmap = NULL;
3434         skinframe->gloss = NULL;
3435         skinframe->glow = NULL;
3436         skinframe->fog = NULL;
3437         skinframe->reflect = NULL;
3438         skinframe->hasalpha = false;
3439
3440         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3441         if (!skindata)
3442                 return NULL;
3443
3444         if (developer_loading.integer)
3445                 Con_Printf("loading quake skin \"%s\"\n", name);
3446
3447         // 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)
3448         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3449         memcpy(skinframe->qpixels, skindata, width*height);
3450         skinframe->qwidth = width;
3451         skinframe->qheight = height;
3452
3453         featuresmask = 0;
3454         for (i = 0;i < width * height;i++)
3455                 featuresmask |= palette_featureflags[skindata[i]];
3456
3457         skinframe->hasalpha = false;
3458         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3459         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3460         skinframe->qgeneratemerged = true;
3461         skinframe->qgeneratebase = skinframe->qhascolormapping;
3462         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3463
3464         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3465         //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]);
3466
3467         return skinframe;
3468 }
3469
3470 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3471 {
3472         int width;
3473         int height;
3474         unsigned char *skindata;
3475
3476         if (!skinframe->qpixels)
3477                 return;
3478
3479         if (!skinframe->qhascolormapping)
3480                 colormapped = false;
3481
3482         if (colormapped)
3483         {
3484                 if (!skinframe->qgeneratebase)
3485                         return;
3486         }
3487         else
3488         {
3489                 if (!skinframe->qgeneratemerged)
3490                         return;
3491         }
3492
3493         width = skinframe->qwidth;
3494         height = skinframe->qheight;
3495         skindata = skinframe->qpixels;
3496
3497         if (skinframe->qgeneratenmap)
3498         {
3499                 unsigned char *temp1, *temp2;
3500                 skinframe->qgeneratenmap = false;
3501                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3502                 temp2 = temp1 + width * height * 4;
3503                 // use either a custom palette or the quake palette
3504                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3505                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3506                 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);
3507                 Mem_Free(temp1);
3508         }
3509
3510         if (skinframe->qgenerateglow)
3511         {
3512                 skinframe->qgenerateglow = false;
3513                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3514         }
3515
3516         if (colormapped)
3517         {
3518                 skinframe->qgeneratebase = false;
3519                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3520                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3521                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3522         }
3523         else
3524         {
3525                 skinframe->qgeneratemerged = false;
3526                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3527         }
3528
3529         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3530         {
3531                 Mem_Free(skinframe->qpixels);
3532                 skinframe->qpixels = NULL;
3533         }
3534 }
3535
3536 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)
3537 {
3538         int i;
3539         skinframe_t *skinframe;
3540
3541         if (cls.state == ca_dedicated)
3542                 return NULL;
3543
3544         // if already loaded just return it, otherwise make a new skinframe
3545         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3546         if (skinframe && skinframe->base)
3547                 return skinframe;
3548
3549         skinframe->stain = NULL;
3550         skinframe->merged = NULL;
3551         skinframe->base = NULL;
3552         skinframe->pants = NULL;
3553         skinframe->shirt = NULL;
3554         skinframe->nmap = NULL;
3555         skinframe->gloss = NULL;
3556         skinframe->glow = NULL;
3557         skinframe->fog = NULL;
3558         skinframe->reflect = NULL;
3559         skinframe->hasalpha = false;
3560
3561         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3562         if (!skindata)
3563                 return NULL;
3564
3565         if (developer_loading.integer)
3566                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3567
3568         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3569         if (textureflags & TEXF_ALPHA)
3570         {
3571                 for (i = 0;i < width * height;i++)
3572                 {
3573                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3574                         {
3575                                 skinframe->hasalpha = true;
3576                                 break;
3577                         }
3578                 }
3579                 if (r_loadfog && skinframe->hasalpha)
3580                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3581         }
3582
3583         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3584         //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]);
3585
3586         return skinframe;
3587 }
3588
3589 skinframe_t *R_SkinFrame_LoadMissing(void)
3590 {
3591         skinframe_t *skinframe;
3592
3593         if (cls.state == ca_dedicated)
3594                 return NULL;
3595
3596         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3597         skinframe->stain = NULL;
3598         skinframe->merged = NULL;
3599         skinframe->base = NULL;
3600         skinframe->pants = NULL;
3601         skinframe->shirt = NULL;
3602         skinframe->nmap = NULL;
3603         skinframe->gloss = NULL;
3604         skinframe->glow = NULL;
3605         skinframe->fog = NULL;
3606         skinframe->reflect = NULL;
3607         skinframe->hasalpha = false;
3608
3609         skinframe->avgcolor[0] = rand() / RAND_MAX;
3610         skinframe->avgcolor[1] = rand() / RAND_MAX;
3611         skinframe->avgcolor[2] = rand() / RAND_MAX;
3612         skinframe->avgcolor[3] = 1;
3613
3614         return skinframe;
3615 }
3616
3617 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3618 typedef struct suffixinfo_s
3619 {
3620         const char *suffix;
3621         qboolean flipx, flipy, flipdiagonal;
3622 }
3623 suffixinfo_t;
3624 static suffixinfo_t suffix[3][6] =
3625 {
3626         {
3627                 {"px",   false, false, false},
3628                 {"nx",   false, false, false},
3629                 {"py",   false, false, false},
3630                 {"ny",   false, false, false},
3631                 {"pz",   false, false, false},
3632                 {"nz",   false, false, false}
3633         },
3634         {
3635                 {"posx", false, false, false},
3636                 {"negx", false, false, false},
3637                 {"posy", false, false, false},
3638                 {"negy", false, false, false},
3639                 {"posz", false, false, false},
3640                 {"negz", false, false, false}
3641         },
3642         {
3643                 {"rt",    true, false,  true},
3644                 {"lf",   false,  true,  true},
3645                 {"ft",    true,  true, false},
3646                 {"bk",   false, false, false},
3647                 {"up",    true, false,  true},
3648                 {"dn",    true, false,  true}
3649         }
3650 };
3651
3652 static int componentorder[4] = {0, 1, 2, 3};
3653
3654 rtexture_t *R_LoadCubemap(const char *basename)
3655 {
3656         int i, j, cubemapsize;
3657         unsigned char *cubemappixels, *image_buffer;
3658         rtexture_t *cubemaptexture;
3659         char name[256];
3660         // must start 0 so the first loadimagepixels has no requested width/height
3661         cubemapsize = 0;
3662         cubemappixels = NULL;
3663         cubemaptexture = NULL;
3664         // keep trying different suffix groups (posx, px, rt) until one loads
3665         for (j = 0;j < 3 && !cubemappixels;j++)
3666         {
3667                 // load the 6 images in the suffix group
3668                 for (i = 0;i < 6;i++)
3669                 {
3670                         // generate an image name based on the base and and suffix
3671                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3672                         // load it
3673                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3674                         {
3675                                 // an image loaded, make sure width and height are equal
3676                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3677                                 {
3678                                         // if this is the first image to load successfully, allocate the cubemap memory
3679                                         if (!cubemappixels && image_width >= 1)
3680                                         {
3681                                                 cubemapsize = image_width;
3682                                                 // note this clears to black, so unavailable sides are black
3683                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3684                                         }
3685                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3686                                         if (cubemappixels)
3687                                                 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);
3688                                 }
3689                                 else
3690                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3691                                 // free the image
3692                                 Mem_Free(image_buffer);
3693                         }
3694                 }
3695         }
3696         // if a cubemap loaded, upload it
3697         if (cubemappixels)
3698         {
3699                 if (developer_loading.integer)
3700                         Con_Printf("loading cubemap \"%s\"\n", basename);
3701
3702                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, r_texture_sRGB_cubemap.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3703                 Mem_Free(cubemappixels);
3704         }
3705         else
3706         {
3707                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3708                 if (developer_loading.integer)
3709                 {
3710                         Con_Printf("(tried tried images ");
3711                         for (j = 0;j < 3;j++)
3712                                 for (i = 0;i < 6;i++)
3713                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3714                         Con_Print(" and was unable to find any of them).\n");
3715                 }
3716         }
3717         return cubemaptexture;
3718 }
3719
3720 rtexture_t *R_GetCubemap(const char *basename)
3721 {
3722         int i;
3723         for (i = 0;i < r_texture_numcubemaps;i++)
3724                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3725                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3726         if (i >= MAX_CUBEMAPS)
3727                 return r_texture_whitecube;
3728         r_texture_numcubemaps++;
3729         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3730         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3731         return r_texture_cubemaps[i].texture;
3732 }
3733
3734 void R_FreeCubemaps(void)
3735 {
3736         int i;
3737         for (i = 0;i < r_texture_numcubemaps;i++)
3738         {
3739                 if (developer_loading.integer)
3740                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3741                 if (r_texture_cubemaps[i].texture)
3742                         R_FreeTexture(r_texture_cubemaps[i].texture);
3743         }
3744         r_texture_numcubemaps = 0;
3745 }
3746
3747 void R_Main_FreeViewCache(void)
3748 {
3749         if (r_refdef.viewcache.entityvisible)
3750                 Mem_Free(r_refdef.viewcache.entityvisible);
3751         if (r_refdef.viewcache.world_pvsbits)
3752                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3753         if (r_refdef.viewcache.world_leafvisible)
3754                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3755         if (r_refdef.viewcache.world_surfacevisible)
3756                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3757         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3758 }
3759
3760 void R_Main_ResizeViewCache(void)
3761 {
3762         int numentities = r_refdef.scene.numentities;
3763         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3764         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3765         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3766         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3767         if (r_refdef.viewcache.maxentities < numentities)
3768         {
3769                 r_refdef.viewcache.maxentities = numentities;
3770                 if (r_refdef.viewcache.entityvisible)
3771                         Mem_Free(r_refdef.viewcache.entityvisible);
3772                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3773         }
3774         if (r_refdef.viewcache.world_numclusters != numclusters)
3775         {
3776                 r_refdef.viewcache.world_numclusters = numclusters;
3777                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3778                 if (r_refdef.viewcache.world_pvsbits)
3779                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3780                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3781         }
3782         if (r_refdef.viewcache.world_numleafs != numleafs)
3783         {
3784                 r_refdef.viewcache.world_numleafs = numleafs;
3785                 if (r_refdef.viewcache.world_leafvisible)
3786                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3787                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3788         }
3789         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3790         {
3791                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3792                 if (r_refdef.viewcache.world_surfacevisible)
3793                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3794                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3795         }
3796 }
3797
3798 extern rtexture_t *loadingscreentexture;
3799 void gl_main_start(void)
3800 {
3801         loadingscreentexture = NULL;
3802         r_texture_blanknormalmap = NULL;
3803         r_texture_white = NULL;
3804         r_texture_grey128 = NULL;
3805         r_texture_black = NULL;
3806         r_texture_whitecube = NULL;
3807         r_texture_normalizationcube = NULL;
3808         r_texture_fogattenuation = NULL;
3809         r_texture_fogheighttexture = NULL;
3810         r_texture_gammaramps = NULL;
3811         r_texture_numcubemaps = 0;
3812
3813         r_loaddds = r_texture_dds_load.integer != 0;
3814         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3815
3816         switch(vid.renderpath)
3817         {
3818         case RENDERPATH_GL20:
3819         case RENDERPATH_D3D9:
3820         case RENDERPATH_D3D10:
3821         case RENDERPATH_D3D11:
3822         case RENDERPATH_SOFT:
3823         case RENDERPATH_GLES2:
3824                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3825                 Cvar_SetValueQuick(&gl_combine, 1);
3826                 Cvar_SetValueQuick(&r_glsl, 1);
3827                 r_loadnormalmap = true;
3828                 r_loadgloss = true;
3829                 r_loadfog = false;
3830                 break;
3831         case RENDERPATH_GL13:
3832                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3833                 Cvar_SetValueQuick(&gl_combine, 1);
3834                 Cvar_SetValueQuick(&r_glsl, 0);
3835                 r_loadnormalmap = false;
3836                 r_loadgloss = false;
3837                 r_loadfog = true;
3838                 break;
3839         case RENDERPATH_GL11:
3840                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3841                 Cvar_SetValueQuick(&gl_combine, 0);
3842                 Cvar_SetValueQuick(&r_glsl, 0);
3843                 r_loadnormalmap = false;
3844                 r_loadgloss = false;
3845                 r_loadfog = true;
3846                 break;
3847         }
3848
3849         R_AnimCache_Free();
3850         R_FrameData_Reset();
3851
3852         r_numqueries = 0;
3853         r_maxqueries = 0;
3854         memset(r_queries, 0, sizeof(r_queries));
3855
3856         r_qwskincache = NULL;
3857         r_qwskincache_size = 0;
3858
3859         // due to caching of texture_t references, the collision cache must be reset
3860         Collision_Cache_Reset(true);
3861
3862         // set up r_skinframe loading system for textures
3863         memset(&r_skinframe, 0, sizeof(r_skinframe));
3864         r_skinframe.loadsequence = 1;
3865         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3866
3867         r_main_texturepool = R_AllocTexturePool();
3868         R_BuildBlankTextures();
3869         R_BuildNoTexture();
3870         if (vid.support.arb_texture_cube_map)
3871         {
3872                 R_BuildWhiteCube();
3873                 R_BuildNormalizationCube();
3874         }
3875         r_texture_fogattenuation = NULL;
3876         r_texture_fogheighttexture = NULL;
3877         r_texture_gammaramps = NULL;
3878         //r_texture_fogintensity = NULL;
3879         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3880         memset(&r_waterstate, 0, sizeof(r_waterstate));
3881         r_glsl_permutation = NULL;
3882         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3883         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3884         glslshaderstring = NULL;
3885 #ifdef SUPPORTD3D
3886         r_hlsl_permutation = NULL;
3887         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3888         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3889 #endif
3890         hlslshaderstring = NULL;
3891         memset(&r_svbsp, 0, sizeof (r_svbsp));
3892
3893         r_refdef.fogmasktable_density = 0;
3894 }
3895
3896 void gl_main_shutdown(void)
3897 {
3898         R_AnimCache_Free();
3899         R_FrameData_Reset();
3900
3901         R_Main_FreeViewCache();
3902
3903         switch(vid.renderpath)
3904         {
3905         case RENDERPATH_GL11:
3906         case RENDERPATH_GL13:
3907         case RENDERPATH_GL20:
3908         case RENDERPATH_GLES2:
3909                 if (r_maxqueries)
3910                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3911                 break;
3912         case RENDERPATH_D3D9:
3913                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3914                 break;
3915         case RENDERPATH_D3D10:
3916                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3917                 break;
3918         case RENDERPATH_D3D11:
3919                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3920                 break;
3921         case RENDERPATH_SOFT:
3922                 break;
3923         }
3924
3925         r_numqueries = 0;
3926         r_maxqueries = 0;
3927         memset(r_queries, 0, sizeof(r_queries));
3928
3929         r_qwskincache = NULL;
3930         r_qwskincache_size = 0;
3931
3932         // clear out the r_skinframe state
3933         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3934         memset(&r_skinframe, 0, sizeof(r_skinframe));
3935
3936         if (r_svbsp.nodes)
3937                 Mem_Free(r_svbsp.nodes);
3938         memset(&r_svbsp, 0, sizeof (r_svbsp));
3939         R_FreeTexturePool(&r_main_texturepool);
3940         loadingscreentexture = NULL;
3941         r_texture_blanknormalmap = NULL;
3942         r_texture_white = NULL;
3943         r_texture_grey128 = NULL;
3944         r_texture_black = NULL;
3945         r_texture_whitecube = NULL;
3946         r_texture_normalizationcube = NULL;
3947         r_texture_fogattenuation = NULL;
3948         r_texture_fogheighttexture = NULL;
3949         r_texture_gammaramps = NULL;
3950         r_texture_numcubemaps = 0;
3951         //r_texture_fogintensity = NULL;
3952         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3953         memset(&r_waterstate, 0, sizeof(r_waterstate));
3954         R_GLSL_Restart_f();
3955
3956         r_glsl_permutation = NULL;
3957         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3958         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3959         glslshaderstring = NULL;
3960 #ifdef SUPPORTD3D
3961         r_hlsl_permutation = NULL;
3962         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3963         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3964 #endif
3965         hlslshaderstring = NULL;
3966 }
3967
3968 extern void CL_ParseEntityLump(char *entitystring);
3969 void gl_main_newmap(void)
3970 {
3971         // FIXME: move this code to client
3972         char *entities, entname[MAX_QPATH];
3973         if (r_qwskincache)
3974                 Mem_Free(r_qwskincache);
3975         r_qwskincache = NULL;
3976         r_qwskincache_size = 0;
3977         if (cl.worldmodel)
3978         {
3979                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3980                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3981                 {
3982                         CL_ParseEntityLump(entities);
3983                         Mem_Free(entities);
3984                         return;
3985                 }
3986                 if (cl.worldmodel->brush.entities)
3987                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3988         }
3989         R_Main_FreeViewCache();
3990
3991         R_FrameData_Reset();
3992 }
3993
3994 void GL_Main_Init(void)
3995 {
3996         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3997
3998         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3999         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4000         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4001         if (gamemode == GAME_NEHAHRA)
4002         {
4003                 Cvar_RegisterVariable (&gl_fogenable);
4004                 Cvar_RegisterVariable (&gl_fogdensity);
4005                 Cvar_RegisterVariable (&gl_fogred);
4006                 Cvar_RegisterVariable (&gl_foggreen);
4007                 Cvar_RegisterVariable (&gl_fogblue);
4008                 Cvar_RegisterVariable (&gl_fogstart);
4009                 Cvar_RegisterVariable (&gl_fogend);
4010                 Cvar_RegisterVariable (&gl_skyclip);
4011         }
4012         Cvar_RegisterVariable(&r_motionblur);
4013         Cvar_RegisterVariable(&r_motionblur_maxblur);
4014         Cvar_RegisterVariable(&r_motionblur_bmin);
4015         Cvar_RegisterVariable(&r_motionblur_vmin);
4016         Cvar_RegisterVariable(&r_motionblur_vmax);
4017         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4018         Cvar_RegisterVariable(&r_motionblur_randomize);
4019         Cvar_RegisterVariable(&r_damageblur);
4020         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4021         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4022         Cvar_RegisterVariable(&r_equalize_entities_by);
4023         Cvar_RegisterVariable(&r_equalize_entities_to);
4024         Cvar_RegisterVariable(&r_depthfirst);
4025         Cvar_RegisterVariable(&r_useinfinitefarclip);
4026         Cvar_RegisterVariable(&r_farclip_base);
4027         Cvar_RegisterVariable(&r_farclip_world);
4028         Cvar_RegisterVariable(&r_nearclip);
4029         Cvar_RegisterVariable(&r_showbboxes);
4030         Cvar_RegisterVariable(&r_showsurfaces);
4031         Cvar_RegisterVariable(&r_showtris);
4032         Cvar_RegisterVariable(&r_shownormals);
4033         Cvar_RegisterVariable(&r_showlighting);
4034         Cvar_RegisterVariable(&r_showshadowvolumes);
4035         Cvar_RegisterVariable(&r_showcollisionbrushes);
4036         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4037         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4038         Cvar_RegisterVariable(&r_showdisabledepthtest);
4039         Cvar_RegisterVariable(&r_drawportals);
4040         Cvar_RegisterVariable(&r_drawentities);
4041         Cvar_RegisterVariable(&r_draw2d);
4042         Cvar_RegisterVariable(&r_drawworld);
4043         Cvar_RegisterVariable(&r_cullentities_trace);
4044         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4045         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4046         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4047         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4048         Cvar_RegisterVariable(&r_drawviewmodel);
4049         Cvar_RegisterVariable(&r_drawexteriormodel);
4050         Cvar_RegisterVariable(&r_speeds);
4051         Cvar_RegisterVariable(&r_fullbrights);
4052         Cvar_RegisterVariable(&r_wateralpha);
4053         Cvar_RegisterVariable(&r_dynamic);
4054         Cvar_RegisterVariable(&r_fakelight);
4055         Cvar_RegisterVariable(&r_fakelight_intensity);
4056         Cvar_RegisterVariable(&r_fullbright);
4057         Cvar_RegisterVariable(&r_shadows);
4058         Cvar_RegisterVariable(&r_shadows_darken);
4059         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4060         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4061         Cvar_RegisterVariable(&r_shadows_throwdistance);
4062         Cvar_RegisterVariable(&r_shadows_throwdirection);
4063         Cvar_RegisterVariable(&r_shadows_focus);
4064         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4065         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4066         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4067         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4068         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4069         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4070         Cvar_RegisterVariable(&r_fog_exp2);
4071         Cvar_RegisterVariable(&r_fog_clear);
4072         Cvar_RegisterVariable(&r_drawfog);
4073         Cvar_RegisterVariable(&r_transparentdepthmasking);
4074         Cvar_RegisterVariable(&r_texture_dds_load);
4075         Cvar_RegisterVariable(&r_texture_dds_save);
4076         Cvar_RegisterVariable(&r_texture_sRGB_2d);
4077         Cvar_RegisterVariable(&r_texture_sRGB_skin_diffuse);
4078         Cvar_RegisterVariable(&r_texture_sRGB_skin_gloss);
4079         Cvar_RegisterVariable(&r_texture_sRGB_skin_glow);
4080         Cvar_RegisterVariable(&r_texture_sRGB_skin_reflect);
4081         Cvar_RegisterVariable(&r_texture_sRGB_cubemap);
4082         Cvar_RegisterVariable(&r_texture_sRGB_skybox);
4083         Cvar_RegisterVariable(&r_textureunits);
4084         Cvar_RegisterVariable(&gl_combine);
4085         Cvar_RegisterVariable(&r_viewfbo);
4086         Cvar_RegisterVariable(&r_viewscale);
4087         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4088         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4089         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4090         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4091         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4092         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4093         Cvar_RegisterVariable(&r_glsl);
4094         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4095         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4096         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4097         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4098         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4099         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4100         Cvar_RegisterVariable(&r_glsl_postprocess);
4101         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4102         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4103         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4104         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4105         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4106         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4107         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4108         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4109
4110         Cvar_RegisterVariable(&r_water);
4111         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4112         Cvar_RegisterVariable(&r_water_clippingplanebias);
4113         Cvar_RegisterVariable(&r_water_refractdistort);
4114         Cvar_RegisterVariable(&r_water_reflectdistort);
4115         Cvar_RegisterVariable(&r_water_scissormode);
4116         Cvar_RegisterVariable(&r_lerpsprites);
4117         Cvar_RegisterVariable(&r_lerpmodels);
4118         Cvar_RegisterVariable(&r_lerplightstyles);
4119         Cvar_RegisterVariable(&r_waterscroll);
4120         Cvar_RegisterVariable(&r_bloom);
4121         Cvar_RegisterVariable(&r_bloom_colorscale);
4122         Cvar_RegisterVariable(&r_bloom_brighten);
4123         Cvar_RegisterVariable(&r_bloom_blur);
4124         Cvar_RegisterVariable(&r_bloom_resolution);
4125         Cvar_RegisterVariable(&r_bloom_colorexponent);
4126         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4127         Cvar_RegisterVariable(&r_hdr);
4128         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4129         Cvar_RegisterVariable(&r_hdr_glowintensity);
4130         Cvar_RegisterVariable(&r_hdr_range);
4131         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4132         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4133         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4134         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4135         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4136         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4137         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4138         Cvar_RegisterVariable(&developer_texturelogging);
4139         Cvar_RegisterVariable(&gl_lightmaps);
4140         Cvar_RegisterVariable(&r_test);
4141         Cvar_RegisterVariable(&r_glsl_saturation);
4142         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4143         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4144         Cvar_RegisterVariable(&r_framedatasize);
4145         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4146                 Cvar_SetValue("r_fullbrights", 0);
4147         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4148
4149         Cvar_RegisterVariable(&r_track_sprites);
4150         Cvar_RegisterVariable(&r_track_sprites_flags);
4151         Cvar_RegisterVariable(&r_track_sprites_scalew);
4152         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4153         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4154         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4155         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4156         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4157 }
4158
4159 extern void R_Textures_Init(void);
4160 extern void GL_Draw_Init(void);
4161 extern void GL_Main_Init(void);
4162 extern void R_Shadow_Init(void);
4163 extern void R_Sky_Init(void);
4164 extern void GL_Surf_Init(void);
4165 extern void R_Particles_Init(void);
4166 extern void R_Explosion_Init(void);
4167 extern void gl_backend_init(void);
4168 extern void Sbar_Init(void);
4169 extern void R_LightningBeams_Init(void);
4170 extern void Mod_RenderInit(void);
4171 extern void Font_Init(void);
4172
4173 void Render_Init(void)
4174 {
4175         gl_backend_init();
4176         R_Textures_Init();
4177         GL_Main_Init();
4178         Font_Init();
4179         GL_Draw_Init();
4180         R_Shadow_Init();
4181         R_Sky_Init();
4182         GL_Surf_Init();
4183         Sbar_Init();
4184         R_Particles_Init();
4185         R_Explosion_Init();
4186         R_LightningBeams_Init();
4187         Mod_RenderInit();
4188 }
4189
4190 /*
4191 ===============
4192 GL_Init
4193 ===============
4194 */
4195 extern char *ENGINE_EXTENSIONS;
4196 void GL_Init (void)
4197 {
4198         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4199         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4200         gl_version = (const char *)qglGetString(GL_VERSION);
4201         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4202
4203         if (!gl_extensions)
4204                 gl_extensions = "";
4205         if (!gl_platformextensions)
4206                 gl_platformextensions = "";
4207
4208         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4209         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4210         Con_Printf("GL_VERSION: %s\n", gl_version);
4211         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4212         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4213
4214         VID_CheckExtensions();
4215
4216         // LordHavoc: report supported extensions
4217         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4218
4219         // clear to black (loading plaque will be seen over this)
4220         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4221 }
4222
4223 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4224 {
4225         int i;
4226         mplane_t *p;
4227         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4228         {
4229                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4230                 if (i == 4)
4231                         continue;
4232                 p = r_refdef.view.frustum + i;
4233                 switch(p->signbits)
4234                 {
4235                 default:
4236                 case 0:
4237                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4238                                 return true;
4239                         break;
4240                 case 1:
4241                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4242                                 return true;
4243                         break;
4244                 case 2:
4245                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4246                                 return true;
4247                         break;
4248                 case 3:
4249                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4250                                 return true;
4251                         break;
4252                 case 4:
4253                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4254                                 return true;
4255                         break;
4256                 case 5:
4257                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4258                                 return true;
4259                         break;
4260                 case 6:
4261                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4262                                 return true;
4263                         break;
4264                 case 7:
4265                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4266                                 return true;
4267                         break;
4268                 }
4269         }
4270         return false;
4271 }
4272
4273 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4274 {
4275         int i;
4276         const mplane_t *p;
4277         for (i = 0;i < numplanes;i++)
4278         {
4279                 p = planes + i;
4280                 switch(p->signbits)
4281                 {
4282                 default:
4283                 case 0:
4284                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4285                                 return true;
4286                         break;
4287                 case 1:
4288                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4289                                 return true;
4290                         break;
4291                 case 2:
4292                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4293                                 return true;
4294                         break;
4295                 case 3:
4296                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4297                                 return true;
4298                         break;
4299                 case 4:
4300                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4301                                 return true;
4302                         break;
4303                 case 5:
4304                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4305                                 return true;
4306                         break;
4307                 case 6:
4308                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4309                                 return true;
4310                         break;
4311                 case 7:
4312                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4313                                 return true;
4314                         break;
4315                 }
4316         }
4317         return false;
4318 }
4319
4320 //==================================================================================
4321
4322 // LordHavoc: this stores temporary data used within the same frame
4323
4324 typedef struct r_framedata_mem_s
4325 {
4326         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4327         size_t size; // how much usable space
4328         size_t current; // how much space in use
4329         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4330         size_t wantedsize; // how much space was allocated
4331         unsigned char *data; // start of real data (16byte aligned)
4332 }
4333 r_framedata_mem_t;
4334
4335 static r_framedata_mem_t *r_framedata_mem;
4336
4337 void R_FrameData_Reset(void)
4338 {
4339         while (r_framedata_mem)
4340         {
4341                 r_framedata_mem_t *next = r_framedata_mem->purge;
4342                 Mem_Free(r_framedata_mem);
4343                 r_framedata_mem = next;
4344         }
4345 }
4346
4347 void R_FrameData_Resize(void)
4348 {
4349         size_t wantedsize;
4350         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4351         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4352         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4353         {
4354                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4355                 newmem->wantedsize = wantedsize;
4356                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4357                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4358                 newmem->current = 0;
4359                 newmem->mark = 0;
4360                 newmem->purge = r_framedata_mem;
4361                 r_framedata_mem = newmem;
4362         }
4363 }
4364
4365 void R_FrameData_NewFrame(void)
4366 {
4367         R_FrameData_Resize();
4368         if (!r_framedata_mem)
4369                 return;
4370         // if we ran out of space on the last frame, free the old memory now
4371         while (r_framedata_mem->purge)
4372         {
4373                 // repeatedly remove the second item in the list, leaving only head
4374                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4375                 Mem_Free(r_framedata_mem->purge);
4376                 r_framedata_mem->purge = next;
4377         }
4378         // reset the current mem pointer
4379         r_framedata_mem->current = 0;
4380         r_framedata_mem->mark = 0;
4381 }
4382
4383 void *R_FrameData_Alloc(size_t size)
4384 {
4385         void *data;
4386
4387         // align to 16 byte boundary - the data pointer is already aligned, so we
4388         // only need to ensure the size of every allocation is also aligned
4389         size = (size + 15) & ~15;
4390
4391         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4392         {
4393                 // emergency - we ran out of space, allocate more memory
4394                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4395                 R_FrameData_Resize();
4396         }
4397
4398         data = r_framedata_mem->data + r_framedata_mem->current;
4399         r_framedata_mem->current += size;
4400
4401         // count the usage for stats
4402         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4403         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4404
4405         return (void *)data;
4406 }
4407
4408 void *R_FrameData_Store(size_t size, void *data)
4409 {
4410         void *d = R_FrameData_Alloc(size);
4411         if (d && data)
4412                 memcpy(d, data, size);
4413         return d;
4414 }
4415
4416 void R_FrameData_SetMark(void)
4417 {
4418         if (!r_framedata_mem)
4419                 return;
4420         r_framedata_mem->mark = r_framedata_mem->current;
4421 }
4422
4423 void R_FrameData_ReturnToMark(void)
4424 {
4425         if (!r_framedata_mem)
4426                 return;
4427         r_framedata_mem->current = r_framedata_mem->mark;
4428 }
4429
4430 //==================================================================================
4431
4432 // LordHavoc: animcache originally written by Echon, rewritten since then
4433
4434 /**
4435  * Animation cache prevents re-generating mesh data for an animated model
4436  * multiple times in one frame for lighting, shadowing, reflections, etc.
4437  */
4438
4439 void R_AnimCache_Free(void)
4440 {
4441 }
4442
4443 void R_AnimCache_ClearCache(void)
4444 {
4445         int i;
4446         entity_render_t *ent;
4447
4448         for (i = 0;i < r_refdef.scene.numentities;i++)
4449         {
4450                 ent = r_refdef.scene.entities[i];
4451                 ent->animcache_vertex3f = NULL;
4452                 ent->animcache_normal3f = NULL;
4453                 ent->animcache_svector3f = NULL;
4454                 ent->animcache_tvector3f = NULL;
4455                 ent->animcache_vertexmesh = NULL;
4456                 ent->animcache_vertex3fbuffer = NULL;
4457                 ent->animcache_vertexmeshbuffer = NULL;
4458         }
4459 }
4460
4461 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4462 {
4463         int i;
4464
4465         // check if we need the meshbuffers
4466         if (!vid.useinterleavedarrays)
4467                 return;
4468
4469         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4470                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4471         // TODO: upload vertex3f buffer?
4472         if (ent->animcache_vertexmesh)
4473         {
4474                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4475                 for (i = 0;i < numvertices;i++)
4476                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4477                 if (ent->animcache_svector3f)
4478                         for (i = 0;i < numvertices;i++)
4479                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4480                 if (ent->animcache_tvector3f)
4481                         for (i = 0;i < numvertices;i++)
4482                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4483                 if (ent->animcache_normal3f)
4484                         for (i = 0;i < numvertices;i++)
4485                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4486                 // TODO: upload vertexmeshbuffer?
4487         }
4488 }
4489
4490 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4491 {
4492         dp_model_t *model = ent->model;
4493         int numvertices;
4494         // see if it's already cached this frame
4495         if (ent->animcache_vertex3f)
4496         {
4497                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4498                 if (wantnormals || wanttangents)
4499                 {
4500                         if (ent->animcache_normal3f)
4501                                 wantnormals = false;
4502                         if (ent->animcache_svector3f)
4503                                 wanttangents = false;
4504                         if (wantnormals || wanttangents)
4505                         {
4506                                 numvertices = model->surfmesh.num_vertices;
4507                                 if (wantnormals)
4508                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4509                                 if (wanttangents)
4510                                 {
4511                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4512                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4513                                 }
4514                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4515                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4516                         }
4517                 }
4518         }
4519         else
4520         {
4521                 // see if this ent is worth caching
4522                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4523                         return false;
4524                 // get some memory for this entity and generate mesh data
4525                 numvertices = model->surfmesh.num_vertices;
4526                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4527                 if (wantnormals)
4528                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4529                 if (wanttangents)
4530                 {
4531                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4532                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4533                 }
4534                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4535                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4536         }
4537         return true;
4538 }
4539
4540 void R_AnimCache_CacheVisibleEntities(void)
4541 {
4542         int i;
4543         qboolean wantnormals = true;
4544         qboolean wanttangents = !r_showsurfaces.integer;
4545
4546         switch(vid.renderpath)
4547         {
4548         case RENDERPATH_GL20:
4549         case RENDERPATH_D3D9:
4550         case RENDERPATH_D3D10:
4551         case RENDERPATH_D3D11:
4552         case RENDERPATH_GLES2:
4553                 break;
4554         case RENDERPATH_GL13:
4555         case RENDERPATH_GL11:
4556                 wanttangents = false;
4557                 break;
4558         case RENDERPATH_SOFT:
4559                 break;
4560         }
4561
4562         if (r_shownormals.integer)
4563                 wanttangents = wantnormals = true;
4564
4565         // TODO: thread this
4566         // NOTE: R_PrepareRTLights() also caches entities
4567
4568         for (i = 0;i < r_refdef.scene.numentities;i++)
4569                 if (r_refdef.viewcache.entityvisible[i])
4570                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4571 }
4572
4573 //==================================================================================
4574
4575 static void R_View_UpdateEntityLighting (void)
4576 {
4577         int i;
4578         entity_render_t *ent;
4579         vec3_t tempdiffusenormal, avg;
4580         vec_t f, fa, fd, fdd;
4581         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4582
4583         for (i = 0;i < r_refdef.scene.numentities;i++)
4584         {
4585                 ent = r_refdef.scene.entities[i];
4586
4587                 // skip unseen models
4588                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4589                         continue;
4590
4591                 // skip bsp models
4592                 if (ent->model && ent->model->brush.num_leafs)
4593                 {
4594                         // TODO: use modellight for r_ambient settings on world?
4595                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4596                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4597                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4598                         continue;
4599                 }
4600
4601                 // fetch the lighting from the worldmodel data
4602                 VectorClear(ent->modellight_ambient);
4603                 VectorClear(ent->modellight_diffuse);
4604                 VectorClear(tempdiffusenormal);
4605                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4606                 {
4607                         vec3_t org;
4608                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4609
4610                         // complete lightning for lit sprites
4611                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4612                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4613                         {
4614                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4615                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4616                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4617                         }
4618                         else
4619                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4620
4621                         if(ent->flags & RENDER_EQUALIZE)
4622                         {
4623                                 // first fix up ambient lighting...
4624                                 if(r_equalize_entities_minambient.value > 0)
4625                                 {
4626                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4627                                         if(fd > 0)
4628                                         {
4629                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4630                                                 if(fa < r_equalize_entities_minambient.value * fd)
4631                                                 {
4632                                                         // solve:
4633                                                         //   fa'/fd' = minambient
4634                                                         //   fa'+0.25*fd' = fa+0.25*fd
4635                                                         //   ...
4636                                                         //   fa' = fd' * minambient
4637                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4638                                                         //   ...
4639                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4640                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4641                                                         //   ...
4642                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4643                                                         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
4644                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4645                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4646                                                 }
4647                                         }
4648                                 }
4649
4650                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4651                                 {
4652                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4653                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4654                                         f = fa + 0.25 * fd;
4655                                         if(f > 0)
4656                                         {
4657                                                 // adjust brightness and saturation to target
4658                                                 avg[0] = avg[1] = avg[2] = fa / f;
4659                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4660                                                 avg[0] = avg[1] = avg[2] = fd / f;
4661                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4662                                         }
4663                                 }
4664                         }
4665                 }
4666                 else // highly rare
4667                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4668
4669                 // move the light direction into modelspace coordinates for lighting code
4670                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4671                 if(VectorLength2(ent->modellight_lightdir) == 0)
4672                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4673                 VectorNormalize(ent->modellight_lightdir);
4674         }
4675 }
4676
4677 #define MAX_LINEOFSIGHTTRACES 64
4678
4679 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4680 {
4681         int i;
4682         vec3_t boxmins, boxmaxs;
4683         vec3_t start;
4684         vec3_t end;
4685         dp_model_t *model = r_refdef.scene.worldmodel;
4686
4687         if (!model || !model->brush.TraceLineOfSight)
4688                 return true;
4689
4690         // expand the box a little
4691         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4692         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4693         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4694         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4695         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4696         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4697
4698         // return true if eye is inside enlarged box
4699         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4700                 return true;
4701
4702         // try center
4703         VectorCopy(eye, start);
4704         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4705         if (model->brush.TraceLineOfSight(model, start, end))
4706                 return true;
4707
4708         // try various random positions
4709         for (i = 0;i < numsamples;i++)
4710         {
4711                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4712                 if (model->brush.TraceLineOfSight(model, start, end))
4713                         return true;
4714         }
4715
4716         return false;
4717 }
4718
4719
4720 static void R_View_UpdateEntityVisible (void)
4721 {
4722         int i;
4723         int renderimask;
4724         int samples;
4725         entity_render_t *ent;
4726
4727         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4728                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4729                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4730                 :                                                          RENDER_EXTERIORMODEL;
4731         if (!r_drawviewmodel.integer)
4732                 renderimask |= RENDER_VIEWMODEL;
4733         if (!r_drawexteriormodel.integer)
4734                 renderimask |= RENDER_EXTERIORMODEL;
4735         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4736         {
4737                 // worldmodel can check visibility
4738                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4739                 for (i = 0;i < r_refdef.scene.numentities;i++)
4740                 {
4741                         ent = r_refdef.scene.entities[i];
4742                         if (!(ent->flags & renderimask))
4743                         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)))
4744                         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))
4745                                 r_refdef.viewcache.entityvisible[i] = true;
4746                 }
4747                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4748                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4749                 {
4750                         for (i = 0;i < r_refdef.scene.numentities;i++)
4751                         {
4752                                 ent = r_refdef.scene.entities[i];
4753                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4754                                 {
4755                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4756                                         if (samples < 0)
4757                                                 continue; // temp entities do pvs only
4758                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4759                                                 ent->last_trace_visibility = realtime;
4760                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4761                                                 r_refdef.viewcache.entityvisible[i] = 0;
4762                                 }
4763                         }
4764                 }
4765         }
4766         else
4767         {
4768                 // no worldmodel or it can't check visibility
4769                 for (i = 0;i < r_refdef.scene.numentities;i++)
4770                 {
4771                         ent = r_refdef.scene.entities[i];
4772                         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));
4773                 }
4774         }
4775 }
4776
4777 /// only used if skyrendermasked, and normally returns false
4778 int R_DrawBrushModelsSky (void)
4779 {
4780         int i, sky;
4781         entity_render_t *ent;
4782
4783         sky = false;
4784         for (i = 0;i < r_refdef.scene.numentities;i++)
4785         {
4786                 if (!r_refdef.viewcache.entityvisible[i])
4787                         continue;
4788                 ent = r_refdef.scene.entities[i];
4789                 if (!ent->model || !ent->model->DrawSky)
4790                         continue;
4791                 ent->model->DrawSky(ent);
4792                 sky = true;
4793         }
4794         return sky;
4795 }
4796
4797 static void R_DrawNoModel(entity_render_t *ent);
4798 static void R_DrawModels(void)
4799 {
4800         int i;
4801         entity_render_t *ent;
4802
4803         for (i = 0;i < r_refdef.scene.numentities;i++)
4804         {
4805                 if (!r_refdef.viewcache.entityvisible[i])
4806                         continue;
4807                 ent = r_refdef.scene.entities[i];
4808                 r_refdef.stats.entities++;
4809                 if (ent->model && ent->model->Draw != NULL)
4810                         ent->model->Draw(ent);
4811                 else
4812                         R_DrawNoModel(ent);
4813         }
4814 }
4815
4816 static void R_DrawModelsDepth(void)
4817 {
4818         int i;
4819         entity_render_t *ent;
4820
4821         for (i = 0;i < r_refdef.scene.numentities;i++)
4822         {
4823                 if (!r_refdef.viewcache.entityvisible[i])
4824                         continue;
4825                 ent = r_refdef.scene.entities[i];
4826                 if (ent->model && ent->model->DrawDepth != NULL)
4827                         ent->model->DrawDepth(ent);
4828         }
4829 }
4830
4831 static void R_DrawModelsDebug(void)
4832 {
4833         int i;
4834         entity_render_t *ent;
4835
4836         for (i = 0;i < r_refdef.scene.numentities;i++)
4837         {
4838                 if (!r_refdef.viewcache.entityvisible[i])
4839                         continue;
4840                 ent = r_refdef.scene.entities[i];
4841                 if (ent->model && ent->model->DrawDebug != NULL)
4842                         ent->model->DrawDebug(ent);
4843         }
4844 }
4845
4846 static void R_DrawModelsAddWaterPlanes(void)
4847 {
4848         int i;
4849         entity_render_t *ent;
4850
4851         for (i = 0;i < r_refdef.scene.numentities;i++)
4852         {
4853                 if (!r_refdef.viewcache.entityvisible[i])
4854                         continue;
4855                 ent = r_refdef.scene.entities[i];
4856                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4857                         ent->model->DrawAddWaterPlanes(ent);
4858         }
4859 }
4860
4861 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4862 {
4863         if (r_hdr_irisadaptation.integer)
4864         {
4865                 vec3_t ambient;
4866                 vec3_t diffuse;
4867                 vec3_t diffusenormal;
4868                 vec_t brightness;
4869                 vec_t goal;
4870                 vec_t adjust;
4871                 vec_t current;
4872                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4873                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4874                 brightness = max(0.0000001f, brightness);
4875                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4876                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4877                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4878                 current = r_hdr_irisadaptation_value.value;
4879                 if (current < goal)
4880                         current = min(current + adjust, goal);
4881                 else if (current > goal)
4882                         current = max(current - adjust, goal);
4883                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4884                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4885         }
4886         else if (r_hdr_irisadaptation_value.value != 1.0f)
4887                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4888 }
4889
4890 static void R_View_SetFrustum(const int *scissor)
4891 {
4892         int i;
4893         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4894         vec3_t forward, left, up, origin, v;
4895
4896         if(scissor)
4897         {
4898                 // flipped x coordinates (because x points left here)
4899                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4900                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4901
4902                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4903                 switch(vid.renderpath)
4904                 {
4905                         case RENDERPATH_D3D9:
4906                         case RENDERPATH_D3D10:
4907                         case RENDERPATH_D3D11:
4908                                 // non-flipped y coordinates
4909                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4910                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4911                                 break;
4912                         case RENDERPATH_SOFT:
4913                         case RENDERPATH_GL11:
4914                         case RENDERPATH_GL13:
4915                         case RENDERPATH_GL20:
4916                         case RENDERPATH_GLES2:
4917                                 // non-flipped y coordinates
4918                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4919                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4920                                 break;
4921                 }
4922         }
4923
4924         // we can't trust r_refdef.view.forward and friends in reflected scenes
4925         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4926
4927 #if 0
4928         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4929         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4930         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4931         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4932         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4933         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4934         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4935         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4936         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4937         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4938         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4939         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4940 #endif
4941
4942 #if 0
4943         zNear = r_refdef.nearclip;
4944         nudge = 1.0 - 1.0 / (1<<23);
4945         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4946         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4947         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4948         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4949         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4950         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4951         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4952         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4953 #endif
4954
4955
4956
4957 #if 0
4958         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4959         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4960         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4961         r_refdef.view.frustum[0].dist = m[15] - m[12];
4962
4963         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4964         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4965         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4966         r_refdef.view.frustum[1].dist = m[15] + m[12];
4967
4968         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4969         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4970         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4971         r_refdef.view.frustum[2].dist = m[15] - m[13];
4972
4973         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4974         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4975         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4976         r_refdef.view.frustum[3].dist = m[15] + m[13];
4977
4978         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4979         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4980         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4981         r_refdef.view.frustum[4].dist = m[15] - m[14];
4982
4983         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4984         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4985         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4986         r_refdef.view.frustum[5].dist = m[15] + m[14];
4987 #endif
4988
4989         if (r_refdef.view.useperspective)
4990         {
4991                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4992                 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]);
4993                 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]);
4994                 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]);
4995                 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]);
4996
4997                 // then the normals from the corners relative to origin
4998                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4999                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5000                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5001                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5002
5003                 // in a NORMAL view, forward cross left == up
5004                 // in a REFLECTED view, forward cross left == down
5005                 // so our cross products above need to be adjusted for a left handed coordinate system
5006                 CrossProduct(forward, left, v);
5007                 if(DotProduct(v, up) < 0)
5008                 {
5009                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5010                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5011                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5012                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5013                 }
5014
5015                 // Leaving those out was a mistake, those were in the old code, and they
5016                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5017                 // I couldn't reproduce it after adding those normalizations. --blub
5018                 VectorNormalize(r_refdef.view.frustum[0].normal);
5019                 VectorNormalize(r_refdef.view.frustum[1].normal);
5020                 VectorNormalize(r_refdef.view.frustum[2].normal);
5021                 VectorNormalize(r_refdef.view.frustum[3].normal);
5022
5023                 // make the corners absolute
5024                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5025                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5026                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5027                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5028
5029                 // one more normal
5030                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5031
5032                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5033                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5034                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5035                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5036                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5037         }
5038         else
5039         {
5040                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5041                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5042                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5043                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5044                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5045                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5046                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5047                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5048                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5049                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5050         }
5051         r_refdef.view.numfrustumplanes = 5;
5052
5053         if (r_refdef.view.useclipplane)
5054         {
5055                 r_refdef.view.numfrustumplanes = 6;
5056                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5057         }
5058
5059         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5060                 PlaneClassify(r_refdef.view.frustum + i);
5061
5062         // LordHavoc: note to all quake engine coders, Quake had a special case
5063         // for 90 degrees which assumed a square view (wrong), so I removed it,
5064         // Quake2 has it disabled as well.
5065
5066         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5067         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5068         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5069         //PlaneClassify(&frustum[0]);
5070
5071         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5072         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5073         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5074         //PlaneClassify(&frustum[1]);
5075
5076         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5077         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5078         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5079         //PlaneClassify(&frustum[2]);
5080
5081         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5082         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5083         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5084         //PlaneClassify(&frustum[3]);
5085
5086         // nearclip plane
5087         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5088         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5089         //PlaneClassify(&frustum[4]);
5090 }
5091
5092 void R_View_UpdateWithScissor(const int *myscissor)
5093 {
5094         R_Main_ResizeViewCache();
5095         R_View_SetFrustum(myscissor);
5096         R_View_WorldVisibility(r_refdef.view.useclipplane);
5097         R_View_UpdateEntityVisible();
5098         R_View_UpdateEntityLighting();
5099 }
5100
5101 void R_View_Update(void)
5102 {
5103         R_Main_ResizeViewCache();
5104         R_View_SetFrustum(NULL);
5105         R_View_WorldVisibility(r_refdef.view.useclipplane);
5106         R_View_UpdateEntityVisible();
5107         R_View_UpdateEntityLighting();
5108 }
5109
5110 float viewscalefpsadjusted = 1.0f;
5111
5112 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5113 {
5114         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5115         scale = bound(0.03125f, scale, 1.0f);
5116         *outwidth = (int)ceil(width * scale);
5117         *outheight = (int)ceil(height * scale);
5118 }
5119
5120 void R_Mesh_SetMainRenderTargets(void)
5121 {
5122         if (r_bloomstate.fbo_framebuffer)
5123                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5124         else
5125                 R_Mesh_ResetRenderTargets();
5126 }
5127
5128 void R_SetupView(qboolean allowwaterclippingplane)
5129 {
5130         const float *customclipplane = NULL;
5131         float plane[4];
5132         int scaledwidth, scaledheight;
5133         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5134         {
5135                 // LordHavoc: couldn't figure out how to make this approach the
5136                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5137                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5138                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5139                         dist = r_refdef.view.clipplane.dist;
5140                 plane[0] = r_refdef.view.clipplane.normal[0];
5141                 plane[1] = r_refdef.view.clipplane.normal[1];
5142                 plane[2] = r_refdef.view.clipplane.normal[2];
5143                 plane[3] = -dist;
5144                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5145         }
5146
5147         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5148         if (!r_refdef.view.useperspective)
5149                 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);
5150         else if (vid.stencil && r_useinfinitefarclip.integer)
5151                 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);
5152         else
5153                 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);
5154         R_Mesh_SetMainRenderTargets();
5155         R_SetViewport(&r_refdef.view.viewport);
5156         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5157         {
5158                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5159                 float screenplane[4];
5160                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5161                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5162                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5163                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5164                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5165         }
5166 }
5167
5168 void R_EntityMatrix(const matrix4x4_t *matrix)
5169 {
5170         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5171         {
5172                 gl_modelmatrixchanged = false;
5173                 gl_modelmatrix = *matrix;
5174                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5175                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5176                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5177                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5178                 CHECKGLERROR
5179                 switch(vid.renderpath)
5180                 {
5181                 case RENDERPATH_D3D9:
5182 #ifdef SUPPORTD3D
5183                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5184                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5185 #endif
5186                         break;
5187                 case RENDERPATH_D3D10:
5188                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5189                         break;
5190                 case RENDERPATH_D3D11:
5191                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5192                         break;
5193                 case RENDERPATH_GL13:
5194                 case RENDERPATH_GL11:
5195                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5196                         break;
5197                 case RENDERPATH_SOFT:
5198                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5199                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5200                         break;
5201                 case RENDERPATH_GL20:
5202                 case RENDERPATH_GLES2:
5203                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5204                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5205                         break;
5206                 }
5207         }
5208 }
5209
5210 void R_ResetViewRendering2D(void)
5211 {
5212         r_viewport_t viewport;
5213         DrawQ_Finish();
5214
5215         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5216         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);
5217         R_Mesh_ResetRenderTargets();
5218         R_SetViewport(&viewport);
5219         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5220         GL_Color(1, 1, 1, 1);
5221         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5222         GL_BlendFunc(GL_ONE, GL_ZERO);
5223         GL_ScissorTest(false);
5224         GL_DepthMask(false);
5225         GL_DepthRange(0, 1);
5226         GL_DepthTest(false);
5227         GL_DepthFunc(GL_LEQUAL);
5228         R_EntityMatrix(&identitymatrix);
5229         R_Mesh_ResetTextureState();
5230         GL_PolygonOffset(0, 0);
5231         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5232         switch(vid.renderpath)
5233         {
5234         case RENDERPATH_GL11:
5235         case RENDERPATH_GL13:
5236         case RENDERPATH_GL20:
5237         case RENDERPATH_GLES2:
5238                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5239                 break;
5240         case RENDERPATH_D3D9:
5241         case RENDERPATH_D3D10:
5242         case RENDERPATH_D3D11:
5243         case RENDERPATH_SOFT:
5244                 break;
5245         }
5246         GL_CullFace(GL_NONE);
5247 }
5248
5249 void R_ResetViewRendering3D(void)
5250 {
5251         DrawQ_Finish();
5252
5253         R_SetupView(true);
5254         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5255         GL_Color(1, 1, 1, 1);
5256         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5257         GL_BlendFunc(GL_ONE, GL_ZERO);
5258         GL_ScissorTest(true);
5259         GL_DepthMask(true);
5260         GL_DepthRange(0, 1);
5261         GL_DepthTest(true);
5262         GL_DepthFunc(GL_LEQUAL);
5263         R_EntityMatrix(&identitymatrix);
5264         R_Mesh_ResetTextureState();
5265         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5266         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5267         switch(vid.renderpath)
5268         {
5269         case RENDERPATH_GL11:
5270         case RENDERPATH_GL13:
5271         case RENDERPATH_GL20:
5272         case RENDERPATH_GLES2:
5273                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5274                 break;
5275         case RENDERPATH_D3D9:
5276         case RENDERPATH_D3D10:
5277         case RENDERPATH_D3D11:
5278         case RENDERPATH_SOFT:
5279                 break;
5280         }
5281         GL_CullFace(r_refdef.view.cullface_back);
5282 }
5283
5284 /*
5285 ================
5286 R_RenderView_UpdateViewVectors
5287 ================
5288 */
5289 static void R_RenderView_UpdateViewVectors(void)
5290 {
5291         // break apart the view matrix into vectors for various purposes
5292         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5293         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5294         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5295         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5296         // make an inverted copy of the view matrix for tracking sprites
5297         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5298 }
5299
5300 void R_RenderScene(void);
5301 void R_RenderWaterPlanes(void);
5302
5303 static void R_Water_StartFrame(void)
5304 {
5305         int i;
5306         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5307         r_waterstate_waterplane_t *p;
5308
5309         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5310                 return;
5311
5312         switch(vid.renderpath)
5313         {
5314         case RENDERPATH_GL20:
5315         case RENDERPATH_D3D9:
5316         case RENDERPATH_D3D10:
5317         case RENDERPATH_D3D11:
5318         case RENDERPATH_SOFT:
5319         case RENDERPATH_GLES2:
5320                 break;
5321         case RENDERPATH_GL13:
5322         case RENDERPATH_GL11:
5323                 return;
5324         }
5325
5326         // set waterwidth and waterheight to the water resolution that will be
5327         // used (often less than the screen resolution for faster rendering)
5328         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5329         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5330
5331         // calculate desired texture sizes
5332         // can't use water if the card does not support the texture size
5333         if (!r_water.integer || r_showsurfaces.integer)
5334                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5335         else if (vid.support.arb_texture_non_power_of_two)
5336         {
5337                 texturewidth = waterwidth;
5338                 textureheight = waterheight;
5339                 camerawidth = waterwidth;
5340                 cameraheight = waterheight;
5341         }
5342         else
5343         {
5344                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5345                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5346                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5347                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5348         }
5349
5350         // allocate textures as needed
5351         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5352         {
5353                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5354                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5355                 {
5356                         if (p->texture_refraction)
5357                                 R_FreeTexture(p->texture_refraction);
5358                         p->texture_refraction = NULL;
5359                         if (p->texture_reflection)
5360                                 R_FreeTexture(p->texture_reflection);
5361                         p->texture_reflection = NULL;
5362                         if (p->texture_camera)
5363                                 R_FreeTexture(p->texture_camera);
5364                         p->texture_camera = NULL;
5365                 }
5366                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5367                 r_waterstate.texturewidth = texturewidth;
5368                 r_waterstate.textureheight = textureheight;
5369                 r_waterstate.camerawidth = camerawidth;
5370                 r_waterstate.cameraheight = cameraheight;
5371         }
5372
5373         if (r_waterstate.texturewidth)
5374         {
5375                 r_waterstate.enabled = true;
5376
5377                 // when doing a reduced render (HDR) we want to use a smaller area
5378                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5379                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5380
5381                 // set up variables that will be used in shader setup
5382                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5383                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5384                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5385                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5386         }
5387
5388         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5389         r_waterstate.numwaterplanes = 0;
5390 }
5391
5392 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5393 {
5394         int triangleindex, planeindex;
5395         const int *e;
5396         vec3_t vert[3];
5397         vec3_t normal;
5398         vec3_t center;
5399         mplane_t plane;
5400         r_waterstate_waterplane_t *p;
5401         texture_t *t = R_GetCurrentTexture(surface->texture);
5402
5403         // just use the first triangle with a valid normal for any decisions
5404         VectorClear(normal);
5405         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5406         {
5407                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5408                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5409                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5410                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5411                 if (VectorLength2(normal) >= 0.001)
5412                         break;
5413         }
5414
5415         VectorCopy(normal, plane.normal);
5416         VectorNormalize(plane.normal);
5417         plane.dist = DotProduct(vert[0], plane.normal);
5418         PlaneClassify(&plane);
5419         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5420         {
5421                 // skip backfaces (except if nocullface is set)
5422                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5423                         return;
5424                 VectorNegate(plane.normal, plane.normal);
5425                 plane.dist *= -1;
5426                 PlaneClassify(&plane);
5427         }
5428
5429
5430         // find a matching plane if there is one
5431         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5432                 if(p->camera_entity == t->camera_entity)
5433                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5434                                 break;
5435         if (planeindex >= r_waterstate.maxwaterplanes)
5436                 return; // nothing we can do, out of planes
5437
5438         // if this triangle does not fit any known plane rendered this frame, add one
5439         if (planeindex >= r_waterstate.numwaterplanes)
5440         {
5441                 // store the new plane
5442                 r_waterstate.numwaterplanes++;
5443                 p->plane = plane;
5444                 // clear materialflags and pvs
5445                 p->materialflags = 0;
5446                 p->pvsvalid = false;
5447                 p->camera_entity = t->camera_entity;
5448                 VectorCopy(surface->mins, p->mins);
5449                 VectorCopy(surface->maxs, p->maxs);
5450         }
5451         else
5452         {
5453                 // merge mins/maxs
5454                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5455                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5456                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5457                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5458                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5459                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5460         }
5461         // merge this surface's materialflags into the waterplane
5462         p->materialflags |= t->currentmaterialflags;
5463         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5464         {
5465                 // merge this surface's PVS into the waterplane
5466                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5467                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5468                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5469                 {
5470                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5471                         p->pvsvalid = true;
5472                 }
5473         }
5474 }
5475
5476 static void R_Water_ProcessPlanes(void)
5477 {
5478         int myscissor[4];
5479         r_refdef_view_t originalview;
5480         r_refdef_view_t myview;
5481         int planeindex;
5482         r_waterstate_waterplane_t *p;
5483         vec3_t visorigin;
5484
5485         originalview = r_refdef.view;
5486
5487         // make sure enough textures are allocated
5488         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5489         {
5490                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5491                 {
5492                         if (!p->texture_refraction)
5493                                 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);
5494                         if (!p->texture_refraction)
5495                                 goto error;
5496                 }
5497                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5498                 {
5499                         if (!p->texture_camera)
5500                                 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);
5501                         if (!p->texture_camera)
5502                                 goto error;
5503                 }
5504
5505                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5506                 {
5507                         if (!p->texture_reflection)
5508                                 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);
5509                         if (!p->texture_reflection)
5510                                 goto error;
5511                 }
5512         }
5513
5514         // render views
5515         r_refdef.view = originalview;
5516         r_refdef.view.showdebug = false;
5517         r_refdef.view.width = r_waterstate.waterwidth;
5518         r_refdef.view.height = r_waterstate.waterheight;
5519         r_refdef.view.useclipplane = true;
5520         myview = r_refdef.view;
5521         r_waterstate.renderingscene = true;
5522         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5523         {
5524                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5525                 {
5526                         r_refdef.view = myview;
5527                         if(r_water_scissormode.integer)
5528                         {
5529                                 R_SetupView(true);
5530                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5531                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5532                         }
5533
5534                         // render reflected scene and copy into texture
5535                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5536                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5537                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5538                         r_refdef.view.clipplane = p->plane;
5539
5540                         // reverse the cullface settings for this render
5541                         r_refdef.view.cullface_front = GL_FRONT;
5542                         r_refdef.view.cullface_back = GL_BACK;
5543                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5544                         {
5545                                 r_refdef.view.usecustompvs = true;
5546                                 if (p->pvsvalid)
5547                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5548                                 else
5549                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5550                         }
5551
5552                         R_ResetViewRendering3D();
5553                         R_ClearScreen(r_refdef.fogenabled);
5554                         if(r_water_scissormode.integer & 2)
5555                                 R_View_UpdateWithScissor(myscissor);
5556                         else
5557                                 R_View_Update();
5558                         if(r_water_scissormode.integer & 1)
5559                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5560                         R_RenderScene();
5561
5562                         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);
5563                 }
5564
5565                 // render the normal view scene and copy into texture
5566                 // (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)
5567                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5568                 {
5569                         r_refdef.view = myview;
5570                         if(r_water_scissormode.integer)
5571                         {
5572                                 R_SetupView(true);
5573                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5574                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5575                         }
5576
5577                         r_waterstate.renderingrefraction = true;
5578
5579                         r_refdef.view.clipplane = p->plane;
5580                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5581                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5582
5583                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5584                         {
5585                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5586                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5587                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5588                                 R_RenderView_UpdateViewVectors();
5589                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5590                                 {
5591                                         r_refdef.view.usecustompvs = true;
5592                                         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);
5593                                 }
5594                         }
5595
5596                         PlaneClassify(&r_refdef.view.clipplane);
5597
5598                         R_ResetViewRendering3D();
5599                         R_ClearScreen(r_refdef.fogenabled);
5600                         if(r_water_scissormode.integer & 2)
5601                                 R_View_UpdateWithScissor(myscissor);
5602                         else
5603                                 R_View_Update();
5604                         if(r_water_scissormode.integer & 1)
5605                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5606                         R_RenderScene();
5607
5608                         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);
5609                         r_waterstate.renderingrefraction = false;
5610                 }
5611                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5612                 {
5613                         r_refdef.view = myview;
5614
5615                         r_refdef.view.clipplane = p->plane;
5616                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5617                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5618
5619                         r_refdef.view.width = r_waterstate.camerawidth;
5620                         r_refdef.view.height = r_waterstate.cameraheight;
5621                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5622                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5623
5624                         if(p->camera_entity)
5625                         {
5626                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5627                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5628                         }
5629
5630                         // note: all of the view is used for displaying... so
5631                         // there is no use in scissoring
5632
5633                         // reverse the cullface settings for this render
5634                         r_refdef.view.cullface_front = GL_FRONT;
5635                         r_refdef.view.cullface_back = GL_BACK;
5636                         // also reverse the view matrix
5637                         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
5638                         R_RenderView_UpdateViewVectors();
5639                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5640                         {
5641                                 r_refdef.view.usecustompvs = true;
5642                                 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);
5643                         }
5644                         
5645                         // camera needs no clipplane
5646                         r_refdef.view.useclipplane = false;
5647
5648                         PlaneClassify(&r_refdef.view.clipplane);
5649
5650                         R_ResetViewRendering3D();
5651                         R_ClearScreen(r_refdef.fogenabled);
5652                         R_View_Update();
5653                         R_RenderScene();
5654
5655                         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);
5656                         r_waterstate.renderingrefraction = false;
5657                 }
5658
5659         }
5660         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5661         r_waterstate.renderingscene = false;
5662         r_refdef.view = originalview;
5663         R_ResetViewRendering3D();
5664         R_ClearScreen(r_refdef.fogenabled);
5665         R_View_Update();
5666         return;
5667 error:
5668         r_refdef.view = originalview;
5669         r_waterstate.renderingscene = false;
5670         Cvar_SetValueQuick(&r_water, 0);
5671         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5672         return;
5673 }
5674
5675 void R_Bloom_StartFrame(void)
5676 {
5677         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5678         int viewwidth, viewheight;
5679         textype_t textype;
5680
5681         if (r_viewscale_fpsscaling.integer)
5682         {
5683                 double actualframetime;
5684                 double targetframetime;
5685                 double adjust;
5686                 actualframetime = r_refdef.lastdrawscreentime;
5687                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5688                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5689                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5690                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5691                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5692                 viewscalefpsadjusted += adjust;
5693                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5694         }
5695         else
5696                 viewscalefpsadjusted = 1.0f;
5697
5698         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5699
5700         switch(vid.renderpath)
5701         {
5702         case RENDERPATH_GL20:
5703         case RENDERPATH_D3D9:
5704         case RENDERPATH_D3D10:
5705         case RENDERPATH_D3D11:
5706         case RENDERPATH_SOFT:
5707         case RENDERPATH_GLES2:
5708                 break;
5709         case RENDERPATH_GL13:
5710         case RENDERPATH_GL11:
5711                 return;
5712         }
5713
5714         // set bloomwidth and bloomheight to the bloom resolution that will be
5715         // used (often less than the screen resolution for faster rendering)
5716         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5717         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5718         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5719         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5720         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5721
5722         // calculate desired texture sizes
5723         if (vid.support.arb_texture_non_power_of_two)
5724         {
5725                 screentexturewidth = vid.width;
5726                 screentextureheight = vid.height;
5727                 bloomtexturewidth = r_bloomstate.bloomwidth;
5728                 bloomtextureheight = r_bloomstate.bloomheight;
5729         }
5730         else
5731         {
5732                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5733                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5734                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5735                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5736         }
5737
5738         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))
5739         {
5740                 Cvar_SetValueQuick(&r_hdr, 0);
5741                 Cvar_SetValueQuick(&r_bloom, 0);
5742                 Cvar_SetValueQuick(&r_motionblur, 0);
5743                 Cvar_SetValueQuick(&r_damageblur, 0);
5744         }
5745
5746         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)
5747                 screentexturewidth = screentextureheight = 0;
5748         if (!r_hdr.integer && !r_bloom.integer)
5749                 bloomtexturewidth = bloomtextureheight = 0;
5750
5751         textype = TEXTYPE_COLORBUFFER;
5752         switch (vid.renderpath)
5753         {
5754         case RENDERPATH_GL20:
5755         case RENDERPATH_GLES2:
5756                 if (vid.support.ext_framebuffer_object)
5757                 {
5758                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5759                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5760                 }
5761                 break;
5762         case RENDERPATH_D3D9:
5763         case RENDERPATH_D3D10:
5764         case RENDERPATH_D3D11:
5765         case RENDERPATH_SOFT:
5766         case RENDERPATH_GL13:
5767         case RENDERPATH_GL11:
5768                 break;
5769         }
5770
5771         // allocate textures as needed
5772         if (r_bloomstate.screentexturewidth != screentexturewidth
5773          || r_bloomstate.screentextureheight != screentextureheight
5774          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5775          || r_bloomstate.bloomtextureheight != bloomtextureheight
5776          || r_bloomstate.texturetype != textype
5777          || r_bloomstate.viewfbo != r_viewfbo.integer)
5778         {
5779                 if (r_bloomstate.texture_bloom)
5780                         R_FreeTexture(r_bloomstate.texture_bloom);
5781                 r_bloomstate.texture_bloom = NULL;
5782                 if (r_bloomstate.texture_screen)
5783                         R_FreeTexture(r_bloomstate.texture_screen);
5784                 r_bloomstate.texture_screen = NULL;
5785                 if (r_bloomstate.fbo_framebuffer)
5786                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5787                 r_bloomstate.fbo_framebuffer = 0;
5788                 if (r_bloomstate.texture_framebuffercolor)
5789                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5790                 r_bloomstate.texture_framebuffercolor = NULL;
5791                 if (r_bloomstate.texture_framebufferdepth)
5792                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5793                 r_bloomstate.texture_framebufferdepth = NULL;
5794                 r_bloomstate.screentexturewidth = screentexturewidth;
5795                 r_bloomstate.screentextureheight = screentextureheight;
5796                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5797                         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);
5798                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5799                 {
5800                         // FIXME: choose depth bits based on a cvar
5801                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5802                         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);
5803                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5804                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5805                         // render depth into one texture and normalmap into the other
5806                         if (qglDrawBuffer)
5807                         {
5808                                 int status;
5809                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5810                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5811                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5812                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5813                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5814                         }
5815                 }
5816                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5817                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5818                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5819                         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);
5820                 r_bloomstate.viewfbo = r_viewfbo.integer;
5821                 r_bloomstate.texturetype = textype;
5822         }
5823
5824         // when doing a reduced render (HDR) we want to use a smaller area
5825         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5826         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5827         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5828         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5829         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5830
5831         // set up a texcoord array for the full resolution screen image
5832         // (we have to keep this around to copy back during final render)
5833         r_bloomstate.screentexcoord2f[0] = 0;
5834         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5835         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5836         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5837         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5838         r_bloomstate.screentexcoord2f[5] = 0;
5839         r_bloomstate.screentexcoord2f[6] = 0;
5840         r_bloomstate.screentexcoord2f[7] = 0;
5841
5842         // set up a texcoord array for the reduced resolution bloom image
5843         // (which will be additive blended over the screen image)
5844         r_bloomstate.bloomtexcoord2f[0] = 0;
5845         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5846         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5847         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5848         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5849         r_bloomstate.bloomtexcoord2f[5] = 0;
5850         r_bloomstate.bloomtexcoord2f[6] = 0;
5851         r_bloomstate.bloomtexcoord2f[7] = 0;
5852
5853         switch(vid.renderpath)
5854         {
5855         case RENDERPATH_GL11:
5856         case RENDERPATH_GL13:
5857         case RENDERPATH_GL20:
5858         case RENDERPATH_SOFT:
5859         case RENDERPATH_GLES2:
5860                 break;
5861         case RENDERPATH_D3D9:
5862         case RENDERPATH_D3D10:
5863         case RENDERPATH_D3D11:
5864                 {
5865                         int i;
5866                         for (i = 0;i < 4;i++)
5867                         {
5868                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5869                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5870                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5871                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5872                         }
5873                 }
5874                 break;
5875         }
5876
5877         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5878         {
5879                 r_bloomstate.enabled = true;
5880                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5881         }
5882
5883         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);
5884
5885         if (r_bloomstate.fbo_framebuffer)
5886                 r_refdef.view.clear = true;
5887 }
5888
5889 void R_Bloom_CopyBloomTexture(float colorscale)
5890 {
5891         r_refdef.stats.bloom++;
5892
5893         // scale down screen texture to the bloom texture size
5894         CHECKGLERROR
5895         R_Mesh_SetMainRenderTargets();
5896         R_SetViewport(&r_bloomstate.viewport);
5897         GL_BlendFunc(GL_ONE, GL_ZERO);
5898         GL_Color(colorscale, colorscale, colorscale, 1);
5899         // 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...
5900         switch(vid.renderpath)
5901         {
5902         case RENDERPATH_GL11:
5903         case RENDERPATH_GL13:
5904         case RENDERPATH_GL20:
5905         case RENDERPATH_SOFT:
5906         case RENDERPATH_GLES2:
5907                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5908                 break;
5909         case RENDERPATH_D3D9:
5910         case RENDERPATH_D3D10:
5911         case RENDERPATH_D3D11:
5912                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5913                 break;
5914         }
5915         // TODO: do boxfilter scale-down in shader?
5916         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5917         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5918         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5919
5920         // we now have a bloom image in the framebuffer
5921         // copy it into the bloom image texture for later processing
5922         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);
5923         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5924 }
5925
5926 void R_Bloom_CopyHDRTexture(void)
5927 {
5928         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);
5929         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5930 }
5931
5932 void R_Bloom_MakeTexture(void)
5933 {
5934         int x, range, dir;
5935         float xoffset, yoffset, r, brighten;
5936
5937         r_refdef.stats.bloom++;
5938
5939         R_ResetViewRendering2D();
5940
5941         // we have a bloom image in the framebuffer
5942         CHECKGLERROR
5943         R_SetViewport(&r_bloomstate.viewport);
5944
5945         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5946         {
5947                 x *= 2;
5948                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5949                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5950                 GL_Color(r,r,r,1);
5951                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5952                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5953                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5954                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5955
5956                 // copy the vertically blurred bloom view to a texture
5957                 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);
5958                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5959         }
5960
5961         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5962         brighten = r_bloom_brighten.value;
5963         if (r_bloomstate.hdr)
5964                 brighten *= r_hdr_range.value;
5965         brighten = sqrt(brighten);
5966         if(range >= 1)
5967                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5968         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5969
5970         for (dir = 0;dir < 2;dir++)
5971         {
5972                 // blend on at multiple vertical offsets to achieve a vertical blur
5973                 // TODO: do offset blends using GLSL
5974                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5975                 GL_BlendFunc(GL_ONE, GL_ZERO);
5976                 for (x = -range;x <= range;x++)
5977                 {
5978                         if (!dir){xoffset = 0;yoffset = x;}
5979                         else {xoffset = x;yoffset = 0;}
5980                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5981                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5982                         // compute a texcoord array with the specified x and y offset
5983                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5984                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5985                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5986                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5987                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5988                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5989                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5990                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5991                         // this r value looks like a 'dot' particle, fading sharply to
5992                         // black at the edges
5993                         // (probably not realistic but looks good enough)
5994                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5995                         //r = brighten/(range*2+1);
5996                         r = brighten / (range * 2 + 1);
5997                         if(range >= 1)
5998                                 r *= (1 - x*x/(float)(range*range));
5999                         GL_Color(r, r, r, 1);
6000                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6001                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6002                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6003                         GL_BlendFunc(GL_ONE, GL_ONE);
6004                 }
6005
6006                 // copy the vertically blurred bloom view to a texture
6007                 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);
6008                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6009         }
6010 }
6011
6012 void R_HDR_RenderBloomTexture(void)
6013 {
6014         int oldwidth, oldheight;
6015         float oldcolorscale;
6016         qboolean oldwaterstate;
6017
6018         oldwaterstate = r_waterstate.enabled;
6019         oldcolorscale = r_refdef.view.colorscale;
6020         oldwidth = r_refdef.view.width;
6021         oldheight = r_refdef.view.height;
6022         r_refdef.view.width = r_bloomstate.bloomwidth;
6023         r_refdef.view.height = r_bloomstate.bloomheight;
6024
6025         if(r_hdr.integer < 2)
6026                 r_waterstate.enabled = false;
6027
6028         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6029         // TODO: add exposure compensation features
6030         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6031
6032         r_refdef.view.showdebug = false;
6033         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6034
6035         R_ResetViewRendering3D();
6036
6037         R_ClearScreen(r_refdef.fogenabled);
6038         if (r_timereport_active)
6039                 R_TimeReport("HDRclear");
6040
6041         R_View_Update();
6042         if (r_timereport_active)
6043                 R_TimeReport("visibility");
6044
6045         // only do secondary renders with HDR if r_hdr is 2 or higher
6046         r_waterstate.numwaterplanes = 0;
6047         if (r_waterstate.enabled)
6048                 R_RenderWaterPlanes();
6049
6050         r_refdef.view.showdebug = true;
6051         R_RenderScene();
6052         r_waterstate.numwaterplanes = 0;
6053
6054         R_ResetViewRendering2D();
6055
6056         R_Bloom_CopyHDRTexture();
6057         R_Bloom_MakeTexture();
6058
6059         // restore the view settings
6060         r_waterstate.enabled = oldwaterstate;
6061         r_refdef.view.width = oldwidth;
6062         r_refdef.view.height = oldheight;
6063         r_refdef.view.colorscale = oldcolorscale;
6064
6065         R_ResetViewRendering3D();
6066
6067         R_ClearScreen(r_refdef.fogenabled);
6068         if (r_timereport_active)
6069                 R_TimeReport("viewclear");
6070 }
6071
6072 static void R_BlendView(void)
6073 {
6074         unsigned int permutation;
6075         float uservecs[4][4];
6076
6077         switch (vid.renderpath)
6078         {
6079         case RENDERPATH_GL20:
6080         case RENDERPATH_D3D9:
6081         case RENDERPATH_D3D10:
6082         case RENDERPATH_D3D11:
6083         case RENDERPATH_SOFT:
6084         case RENDERPATH_GLES2:
6085                 permutation =
6086                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6087                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6088                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6089                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6090                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6091
6092                 if (r_bloomstate.texture_screen)
6093                 {
6094                         // make sure the buffer is available
6095                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6096
6097                         R_ResetViewRendering2D();
6098                         R_Mesh_SetMainRenderTargets();
6099
6100                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6101                         {
6102                                 // declare variables
6103                                 float speed;
6104                                 static float avgspeed;
6105
6106                                 speed = VectorLength(cl.movement_velocity);
6107
6108                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6109                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6110
6111                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6112                                 speed = bound(0, speed, 1);
6113                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6114
6115                                 // calculate values into a standard alpha
6116                                 cl.motionbluralpha = 1 - exp(-
6117                                                 (
6118                                                  (r_motionblur.value * speed / 80)
6119                                                  +
6120                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6121                                                 )
6122                                                 /
6123                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6124                                            );
6125
6126                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6127                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6128                                 // apply the blur
6129                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6130                                 {
6131                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6132                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6133                                         switch(vid.renderpath)
6134                                         {
6135                                         case RENDERPATH_GL11:
6136                                         case RENDERPATH_GL13:
6137                                         case RENDERPATH_GL20:
6138                                         case RENDERPATH_SOFT:
6139                                         case RENDERPATH_GLES2:
6140                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6141                                                 break;
6142                                         case RENDERPATH_D3D9:
6143                                         case RENDERPATH_D3D10:
6144                                         case RENDERPATH_D3D11:
6145                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6146                                                 break;
6147                                         }
6148                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6149                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6150                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6151                                 }
6152                         }
6153
6154                         // copy view into the screen texture
6155                         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);
6156                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6157                 }
6158                 else if (!r_bloomstate.texture_bloom)
6159                 {
6160                         // we may still have to do view tint...
6161                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6162                         {
6163                                 // apply a color tint to the whole view
6164                                 R_ResetViewRendering2D();
6165                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6166                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6167                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6168                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6169                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6170                         }
6171                         break; // no screen processing, no bloom, skip it
6172                 }
6173
6174                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6175                 {
6176                         // render simple bloom effect
6177                         // copy the screen and shrink it and darken it for the bloom process
6178                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6179                         // make the bloom texture
6180                         R_Bloom_MakeTexture();
6181                 }
6182
6183 #if _MSC_VER >= 1400
6184 #define sscanf sscanf_s
6185 #endif
6186                 memset(uservecs, 0, sizeof(uservecs));
6187                 if (r_glsl_postprocess_uservec1_enable.integer)
6188                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6189                 if (r_glsl_postprocess_uservec2_enable.integer)
6190                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6191                 if (r_glsl_postprocess_uservec3_enable.integer)
6192                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6193                 if (r_glsl_postprocess_uservec4_enable.integer)
6194                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6195
6196                 R_ResetViewRendering2D();
6197                 GL_Color(1, 1, 1, 1);
6198                 GL_BlendFunc(GL_ONE, GL_ZERO);
6199
6200                 switch(vid.renderpath)
6201                 {
6202                 case RENDERPATH_GL20:
6203                 case RENDERPATH_GLES2:
6204                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6205                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6206                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6207                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6208                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6209                         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]);
6210                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6211                         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]);
6212                         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]);
6213                         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]);
6214                         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]);
6215                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6216                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6217                         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);
6218                         break;
6219                 case RENDERPATH_D3D9:
6220 #ifdef SUPPORTD3D
6221                         // 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...
6222                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6223                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6224                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6225                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6226                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6227                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6228                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6229                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6230                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6231                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6232                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6233                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6234                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6235                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6236 #endif
6237                         break;
6238                 case RENDERPATH_D3D10:
6239                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6240                         break;
6241                 case RENDERPATH_D3D11:
6242                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6243                         break;
6244                 case RENDERPATH_SOFT:
6245                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6246                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6247                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6248                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6249                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6250                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6251                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6252                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6253                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6254                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6255                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6256                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6257                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6258                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6259                         break;
6260                 default:
6261                         break;
6262                 }
6263                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6264                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6265                 break;
6266         case RENDERPATH_GL13:
6267         case RENDERPATH_GL11:
6268                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6269                 {
6270                         // apply a color tint to the whole view
6271                         R_ResetViewRendering2D();
6272                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6273                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6274                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6275                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6276                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6277                 }
6278                 break;
6279         }
6280 }
6281
6282 matrix4x4_t r_waterscrollmatrix;
6283
6284 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6285 {
6286         if (r_refdef.fog_density)
6287         {
6288                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6289                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6290                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6291
6292                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6293                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6294                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6295                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6296
6297                 {
6298                         vec3_t fogvec;
6299                         VectorCopy(r_refdef.fogcolor, fogvec);
6300                         //   color.rgb *= ContrastBoost * SceneBrightness;
6301                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6302                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6303                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6304                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6305                 }
6306         }
6307 }
6308
6309 void R_UpdateVariables(void)
6310 {
6311         R_Textures_Frame();
6312
6313         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6314
6315         r_refdef.farclip = r_farclip_base.value;
6316         if (r_refdef.scene.worldmodel)
6317                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6318         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6319
6320         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6321                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6322         r_refdef.polygonfactor = 0;
6323         r_refdef.polygonoffset = 0;
6324         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6325         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6326
6327         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6328         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6329         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6330         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6331         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6332         if (FAKELIGHT_ENABLED)
6333         {
6334                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6335         }
6336         if (r_showsurfaces.integer)
6337         {
6338                 r_refdef.scene.rtworld = false;
6339                 r_refdef.scene.rtworldshadows = false;
6340                 r_refdef.scene.rtdlight = false;
6341                 r_refdef.scene.rtdlightshadows = false;
6342                 r_refdef.lightmapintensity = 0;
6343         }
6344
6345         if (gamemode == GAME_NEHAHRA)
6346         {
6347                 if (gl_fogenable.integer)
6348                 {
6349                         r_refdef.oldgl_fogenable = true;
6350                         r_refdef.fog_density = gl_fogdensity.value;
6351                         r_refdef.fog_red = gl_fogred.value;
6352                         r_refdef.fog_green = gl_foggreen.value;
6353                         r_refdef.fog_blue = gl_fogblue.value;
6354                         r_refdef.fog_alpha = 1;
6355                         r_refdef.fog_start = 0;
6356                         r_refdef.fog_end = gl_skyclip.value;
6357                         r_refdef.fog_height = 1<<30;
6358                         r_refdef.fog_fadedepth = 128;
6359                 }
6360                 else if (r_refdef.oldgl_fogenable)
6361                 {
6362                         r_refdef.oldgl_fogenable = false;
6363                         r_refdef.fog_density = 0;
6364                         r_refdef.fog_red = 0;
6365                         r_refdef.fog_green = 0;
6366                         r_refdef.fog_blue = 0;
6367                         r_refdef.fog_alpha = 0;
6368                         r_refdef.fog_start = 0;
6369                         r_refdef.fog_end = 0;
6370                         r_refdef.fog_height = 1<<30;
6371                         r_refdef.fog_fadedepth = 128;
6372                 }
6373         }
6374
6375         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6376         r_refdef.fog_start = max(0, r_refdef.fog_start);
6377         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6378
6379         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6380
6381         if (r_refdef.fog_density && r_drawfog.integer)
6382         {
6383                 r_refdef.fogenabled = true;
6384                 // this is the point where the fog reaches 0.9986 alpha, which we
6385                 // consider a good enough cutoff point for the texture
6386                 // (0.9986 * 256 == 255.6)
6387                 if (r_fog_exp2.integer)
6388                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6389                 else
6390                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6391                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6392                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6393                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6394                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6395                         R_BuildFogHeightTexture();
6396                 // fog color was already set
6397                 // update the fog texture
6398                 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)
6399                         R_BuildFogTexture();
6400                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6401                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6402         }
6403         else
6404                 r_refdef.fogenabled = false;
6405
6406         switch(vid.renderpath)
6407         {
6408         case RENDERPATH_GL20:
6409         case RENDERPATH_D3D9:
6410         case RENDERPATH_D3D10:
6411         case RENDERPATH_D3D11:
6412         case RENDERPATH_SOFT:
6413         case RENDERPATH_GLES2:
6414                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6415                 {
6416                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6417                         {
6418                                 // build GLSL gamma texture
6419 #define RAMPWIDTH 256
6420                                 unsigned short ramp[RAMPWIDTH * 3];
6421                                 unsigned char rampbgr[RAMPWIDTH][4];
6422                                 int i;
6423
6424                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6425
6426                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6427                                 for(i = 0; i < RAMPWIDTH; ++i)
6428                                 {
6429                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6430                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6431                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6432                                         rampbgr[i][3] = 0;
6433                                 }
6434                                 if (r_texture_gammaramps)
6435                                 {
6436                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6437                                 }
6438                                 else
6439                                 {
6440                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6441                                 }
6442                         }
6443                 }
6444                 else
6445                 {
6446                         // remove GLSL gamma texture
6447                 }
6448                 break;
6449         case RENDERPATH_GL13:
6450         case RENDERPATH_GL11:
6451                 break;
6452         }
6453 }
6454
6455 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6456 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6457 /*
6458 ================
6459 R_SelectScene
6460 ================
6461 */
6462 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6463         if( scenetype != r_currentscenetype ) {
6464                 // store the old scenetype
6465                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6466                 r_currentscenetype = scenetype;
6467                 // move in the new scene
6468                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6469         }
6470 }
6471
6472 /*
6473 ================
6474 R_GetScenePointer
6475 ================
6476 */
6477 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6478 {
6479         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6480         if( scenetype == r_currentscenetype ) {
6481                 return &r_refdef.scene;
6482         } else {
6483                 return &r_scenes_store[ scenetype ];
6484         }
6485 }
6486
6487 /*
6488 ================
6489 R_RenderView
6490 ================
6491 */
6492 int dpsoftrast_test;
6493 void R_RenderView(void)
6494 {
6495         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6496
6497         dpsoftrast_test = r_test.integer;
6498
6499         if (r_timereport_active)
6500                 R_TimeReport("start");
6501         r_textureframe++; // used only by R_GetCurrentTexture
6502         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6503
6504         if(R_CompileShader_CheckStaticParms())
6505                 R_GLSL_Restart_f();
6506
6507         if (!r_drawentities.integer)
6508                 r_refdef.scene.numentities = 0;
6509
6510         R_AnimCache_ClearCache();
6511         R_FrameData_NewFrame();
6512
6513         /* adjust for stereo display */
6514         if(R_Stereo_Active())
6515         {
6516                 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);
6517                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6518         }
6519
6520         if (r_refdef.view.isoverlay)
6521         {
6522                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6523                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6524                 R_TimeReport("depthclear");
6525
6526                 r_refdef.view.showdebug = false;
6527
6528                 r_waterstate.enabled = false;
6529                 r_waterstate.numwaterplanes = 0;
6530
6531                 R_RenderScene();
6532
6533                 r_refdef.view.matrix = originalmatrix;
6534
6535                 CHECKGLERROR
6536                 return;
6537         }
6538
6539         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6540         {
6541                 r_refdef.view.matrix = originalmatrix;
6542                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6543         }
6544
6545         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6546
6547         R_RenderView_UpdateViewVectors();
6548
6549         R_Shadow_UpdateWorldLightSelection();
6550
6551         R_Bloom_StartFrame();
6552         R_Water_StartFrame();
6553
6554         CHECKGLERROR
6555         if (r_timereport_active)
6556                 R_TimeReport("viewsetup");
6557
6558         R_ResetViewRendering3D();
6559
6560         if (r_refdef.view.clear || r_refdef.fogenabled)
6561         {
6562                 R_ClearScreen(r_refdef.fogenabled);
6563                 if (r_timereport_active)
6564                         R_TimeReport("viewclear");
6565         }
6566         r_refdef.view.clear = true;
6567
6568         // this produces a bloom texture to be used in R_BlendView() later
6569         if (r_bloomstate.hdr)
6570         {
6571                 R_HDR_RenderBloomTexture();
6572                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6573                 r_textureframe++; // used only by R_GetCurrentTexture
6574         }
6575
6576         r_refdef.view.showdebug = true;
6577
6578         R_View_Update();
6579         if (r_timereport_active)
6580                 R_TimeReport("visibility");
6581
6582         r_waterstate.numwaterplanes = 0;
6583         if (r_waterstate.enabled)
6584                 R_RenderWaterPlanes();
6585
6586         R_RenderScene();
6587         r_waterstate.numwaterplanes = 0;
6588
6589         R_BlendView();
6590         if (r_timereport_active)
6591                 R_TimeReport("blendview");
6592
6593         GL_Scissor(0, 0, vid.width, vid.height);
6594         GL_ScissorTest(false);
6595
6596         r_refdef.view.matrix = originalmatrix;
6597
6598         CHECKGLERROR
6599 }
6600
6601 void R_RenderWaterPlanes(void)
6602 {
6603         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6604         {
6605                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6606                 if (r_timereport_active)
6607                         R_TimeReport("waterworld");
6608         }
6609
6610         // don't let sound skip if going slow
6611         if (r_refdef.scene.extraupdate)
6612                 S_ExtraUpdate ();
6613
6614         R_DrawModelsAddWaterPlanes();
6615         if (r_timereport_active)
6616                 R_TimeReport("watermodels");
6617
6618         if (r_waterstate.numwaterplanes)
6619         {
6620                 R_Water_ProcessPlanes();
6621                 if (r_timereport_active)
6622                         R_TimeReport("waterscenes");
6623         }
6624 }
6625
6626 extern void R_DrawLightningBeams (void);
6627 extern void VM_CL_AddPolygonsToMeshQueue (void);
6628 extern void R_DrawPortals (void);
6629 extern cvar_t cl_locs_show;
6630 static void R_DrawLocs(void);
6631 static void R_DrawEntityBBoxes(void);
6632 static void R_DrawModelDecals(void);
6633 extern void R_DrawModelShadows(void);
6634 extern void R_DrawModelShadowMaps(void);
6635 extern cvar_t cl_decals_newsystem;
6636 extern qboolean r_shadow_usingdeferredprepass;
6637 void R_RenderScene(void)
6638 {
6639         qboolean shadowmapping = false;
6640
6641         if (r_timereport_active)
6642                 R_TimeReport("beginscene");
6643
6644         r_refdef.stats.renders++;
6645
6646         R_UpdateFogColor();
6647
6648         // don't let sound skip if going slow
6649         if (r_refdef.scene.extraupdate)
6650                 S_ExtraUpdate ();
6651
6652         R_MeshQueue_BeginScene();
6653
6654         R_SkyStartFrame();
6655
6656         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);
6657
6658         if (r_timereport_active)
6659                 R_TimeReport("skystartframe");
6660
6661         if (cl.csqc_vidvars.drawworld)
6662         {
6663                 // don't let sound skip if going slow
6664                 if (r_refdef.scene.extraupdate)
6665                         S_ExtraUpdate ();
6666
6667                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6668                 {
6669                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6670                         if (r_timereport_active)
6671                                 R_TimeReport("worldsky");
6672                 }
6673
6674                 if (R_DrawBrushModelsSky() && r_timereport_active)
6675                         R_TimeReport("bmodelsky");
6676
6677                 if (skyrendermasked && skyrenderlater)
6678                 {
6679                         // we have to force off the water clipping plane while rendering sky
6680                         R_SetupView(false);
6681                         R_Sky();
6682                         R_SetupView(true);
6683                         if (r_timereport_active)
6684                                 R_TimeReport("sky");
6685                 }
6686         }
6687
6688         R_AnimCache_CacheVisibleEntities();
6689         if (r_timereport_active)
6690                 R_TimeReport("animation");
6691
6692         R_Shadow_PrepareLights();
6693         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6694                 R_Shadow_PrepareModelShadows();
6695         if (r_timereport_active)
6696                 R_TimeReport("preparelights");
6697
6698         if (R_Shadow_ShadowMappingEnabled())
6699                 shadowmapping = true;
6700
6701         if (r_shadow_usingdeferredprepass)
6702                 R_Shadow_DrawPrepass();
6703
6704         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6705         {
6706                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6707                 if (r_timereport_active)
6708                         R_TimeReport("worlddepth");
6709         }
6710         if (r_depthfirst.integer >= 2)
6711         {
6712                 R_DrawModelsDepth();
6713                 if (r_timereport_active)
6714                         R_TimeReport("modeldepth");
6715         }
6716
6717         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6718         {
6719                 R_DrawModelShadowMaps();
6720                 R_ResetViewRendering3D();
6721                 // don't let sound skip if going slow
6722                 if (r_refdef.scene.extraupdate)
6723                         S_ExtraUpdate ();
6724         }
6725
6726         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6727         {
6728                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6729                 if (r_timereport_active)
6730                         R_TimeReport("world");
6731         }
6732
6733         // don't let sound skip if going slow
6734         if (r_refdef.scene.extraupdate)
6735                 S_ExtraUpdate ();
6736
6737         R_DrawModels();
6738         if (r_timereport_active)
6739                 R_TimeReport("models");
6740
6741         // don't let sound skip if going slow
6742         if (r_refdef.scene.extraupdate)
6743                 S_ExtraUpdate ();
6744
6745         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6746         {
6747                 R_DrawModelShadows();
6748                 R_ResetViewRendering3D();
6749                 // don't let sound skip if going slow
6750                 if (r_refdef.scene.extraupdate)
6751                         S_ExtraUpdate ();
6752         }
6753
6754         if (!r_shadow_usingdeferredprepass)
6755         {
6756                 R_Shadow_DrawLights();
6757                 if (r_timereport_active)
6758                         R_TimeReport("rtlights");
6759         }
6760
6761         // don't let sound skip if going slow
6762         if (r_refdef.scene.extraupdate)
6763                 S_ExtraUpdate ();
6764
6765         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6766         {
6767                 R_DrawModelShadows();
6768                 R_ResetViewRendering3D();
6769                 // don't let sound skip if going slow
6770                 if (r_refdef.scene.extraupdate)
6771                         S_ExtraUpdate ();
6772         }
6773
6774         if (cl.csqc_vidvars.drawworld)
6775         {
6776                 if (cl_decals_newsystem.integer)
6777                 {
6778                         R_DrawModelDecals();
6779                         if (r_timereport_active)
6780                                 R_TimeReport("modeldecals");
6781                 }
6782                 else
6783                 {
6784                         R_DrawDecals();
6785                         if (r_timereport_active)
6786                                 R_TimeReport("decals");
6787                 }
6788
6789                 R_DrawParticles();
6790                 if (r_timereport_active)
6791                         R_TimeReport("particles");
6792
6793                 R_DrawExplosions();
6794                 if (r_timereport_active)
6795                         R_TimeReport("explosions");
6796
6797                 R_DrawLightningBeams();
6798                 if (r_timereport_active)
6799                         R_TimeReport("lightning");
6800         }
6801
6802         VM_CL_AddPolygonsToMeshQueue();
6803
6804         if (r_refdef.view.showdebug)
6805         {
6806                 if (cl_locs_show.integer)
6807                 {
6808                         R_DrawLocs();
6809                         if (r_timereport_active)
6810                                 R_TimeReport("showlocs");
6811                 }
6812
6813                 if (r_drawportals.integer)
6814                 {
6815                         R_DrawPortals();
6816                         if (r_timereport_active)
6817                                 R_TimeReport("portals");
6818                 }
6819
6820                 if (r_showbboxes.value > 0)
6821                 {
6822                         R_DrawEntityBBoxes();
6823                         if (r_timereport_active)
6824                                 R_TimeReport("bboxes");
6825                 }
6826         }
6827
6828         R_MeshQueue_RenderTransparent();
6829         if (r_timereport_active)
6830                 R_TimeReport("drawtrans");
6831
6832         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))
6833         {
6834                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6835                 if (r_timereport_active)
6836                         R_TimeReport("worlddebug");
6837                 R_DrawModelsDebug();
6838                 if (r_timereport_active)
6839                         R_TimeReport("modeldebug");
6840         }
6841
6842         if (cl.csqc_vidvars.drawworld)
6843         {
6844                 R_Shadow_DrawCoronas();
6845                 if (r_timereport_active)
6846                         R_TimeReport("coronas");
6847         }
6848
6849 #if 0
6850         {
6851                 GL_DepthTest(false);
6852                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6853                 GL_Color(1, 1, 1, 1);
6854                 qglBegin(GL_POLYGON);
6855                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6856                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6857                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6858                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6859                 qglEnd();
6860                 qglBegin(GL_POLYGON);
6861                 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]);
6862                 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]);
6863                 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]);
6864                 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]);
6865                 qglEnd();
6866                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6867         }
6868 #endif
6869
6870         // don't let sound skip if going slow
6871         if (r_refdef.scene.extraupdate)
6872                 S_ExtraUpdate ();
6873
6874         R_ResetViewRendering2D();
6875 }
6876
6877 static const unsigned short bboxelements[36] =
6878 {
6879         5, 1, 3, 5, 3, 7,
6880         6, 2, 0, 6, 0, 4,
6881         7, 3, 2, 7, 2, 6,
6882         4, 0, 1, 4, 1, 5,
6883         4, 5, 7, 4, 7, 6,
6884         1, 0, 2, 1, 2, 3,
6885 };
6886
6887 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6888 {
6889         int i;
6890         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6891
6892         RSurf_ActiveWorldEntity();
6893
6894         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6895         GL_DepthMask(false);
6896         GL_DepthRange(0, 1);
6897         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6898 //      R_Mesh_ResetTextureState();
6899
6900         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6901         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6902         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6903         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6904         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6905         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6906         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6907         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6908         R_FillColors(color4f, 8, cr, cg, cb, ca);
6909         if (r_refdef.fogenabled)
6910         {
6911                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6912                 {
6913                         f1 = RSurf_FogVertex(v);
6914                         f2 = 1 - f1;
6915                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6916                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6917                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6918                 }
6919         }
6920         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6921         R_Mesh_ResetTextureState();
6922         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6923         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6924 }
6925
6926 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6927 {
6928         int i;
6929         float color[4];
6930         prvm_edict_t *edict;
6931         prvm_prog_t *prog_save = prog;
6932
6933         // this function draws bounding boxes of server entities
6934         if (!sv.active)
6935                 return;
6936
6937         GL_CullFace(GL_NONE);
6938         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6939
6940         prog = 0;
6941         SV_VM_Begin();
6942         for (i = 0;i < numsurfaces;i++)
6943         {
6944                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6945                 switch ((int)edict->fields.server->solid)
6946                 {
6947                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6948                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6949                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6950                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6951                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6952                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6953                 }
6954                 color[3] *= r_showbboxes.value;
6955                 color[3] = bound(0, color[3], 1);
6956                 GL_DepthTest(!r_showdisabledepthtest.integer);
6957                 GL_CullFace(r_refdef.view.cullface_front);
6958                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6959         }
6960         SV_VM_End();
6961         prog = prog_save;
6962 }
6963
6964 static void R_DrawEntityBBoxes(void)
6965 {
6966         int i;
6967         prvm_edict_t *edict;
6968         vec3_t center;
6969         prvm_prog_t *prog_save = prog;
6970
6971         // this function draws bounding boxes of server entities
6972         if (!sv.active)
6973                 return;
6974
6975         prog = 0;
6976         SV_VM_Begin();
6977         for (i = 0;i < prog->num_edicts;i++)
6978         {
6979                 edict = PRVM_EDICT_NUM(i);
6980                 if (edict->priv.server->free)
6981                         continue;
6982                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6983                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6984                         continue;
6985                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6986                         continue;
6987                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6988                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6989         }
6990         SV_VM_End();
6991         prog = prog_save;
6992 }
6993
6994 static const int nomodelelement3i[24] =
6995 {
6996         5, 2, 0,
6997         5, 1, 2,
6998         5, 0, 3,
6999         5, 3, 1,
7000         0, 2, 4,
7001         2, 1, 4,
7002         3, 0, 4,
7003         1, 3, 4
7004 };
7005
7006 static const unsigned short nomodelelement3s[24] =
7007 {
7008         5, 2, 0,
7009         5, 1, 2,
7010         5, 0, 3,
7011         5, 3, 1,
7012         0, 2, 4,
7013         2, 1, 4,
7014         3, 0, 4,
7015         1, 3, 4
7016 };
7017
7018 static const float nomodelvertex3f[6*3] =
7019 {
7020         -16,   0,   0,
7021          16,   0,   0,
7022           0, -16,   0,
7023           0,  16,   0,
7024           0,   0, -16,
7025           0,   0,  16
7026 };
7027
7028 static const float nomodelcolor4f[6*4] =
7029 {
7030         0.0f, 0.0f, 0.5f, 1.0f,
7031         0.0f, 0.0f, 0.5f, 1.0f,
7032         0.0f, 0.5f, 0.0f, 1.0f,
7033         0.0f, 0.5f, 0.0f, 1.0f,
7034         0.5f, 0.0f, 0.0f, 1.0f,
7035         0.5f, 0.0f, 0.0f, 1.0f
7036 };
7037
7038 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7039 {
7040         int i;
7041         float f1, f2, *c;
7042         float color4f[6*4];
7043
7044         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);
7045
7046         // this is only called once per entity so numsurfaces is always 1, and
7047         // surfacelist is always {0}, so this code does not handle batches
7048
7049         if (rsurface.ent_flags & RENDER_ADDITIVE)
7050         {
7051                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7052                 GL_DepthMask(false);
7053         }
7054         else if (rsurface.colormod[3] < 1)
7055         {
7056                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7057                 GL_DepthMask(false);
7058         }
7059         else
7060         {
7061                 GL_BlendFunc(GL_ONE, GL_ZERO);
7062                 GL_DepthMask(true);
7063         }
7064         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7065         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7066         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7067         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7068         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7069         for (i = 0, c = color4f;i < 6;i++, c += 4)
7070         {
7071                 c[0] *= rsurface.colormod[0];
7072                 c[1] *= rsurface.colormod[1];
7073                 c[2] *= rsurface.colormod[2];
7074                 c[3] *= rsurface.colormod[3];
7075         }
7076         if (r_refdef.fogenabled)
7077         {
7078                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7079                 {
7080                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7081                         f2 = 1 - f1;
7082                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7083                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7084                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7085                 }
7086         }
7087 //      R_Mesh_ResetTextureState();
7088         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7089         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7090         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7091 }
7092
7093 void R_DrawNoModel(entity_render_t *ent)
7094 {
7095         vec3_t org;
7096         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7097         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7098                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7099         else
7100                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7101 }
7102
7103 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7104 {
7105         vec3_t right1, right2, diff, normal;
7106
7107         VectorSubtract (org2, org1, normal);
7108
7109         // calculate 'right' vector for start
7110         VectorSubtract (r_refdef.view.origin, org1, diff);
7111         CrossProduct (normal, diff, right1);
7112         VectorNormalize (right1);
7113
7114         // calculate 'right' vector for end
7115         VectorSubtract (r_refdef.view.origin, org2, diff);
7116         CrossProduct (normal, diff, right2);
7117         VectorNormalize (right2);
7118
7119         vert[ 0] = org1[0] + width * right1[0];
7120         vert[ 1] = org1[1] + width * right1[1];
7121         vert[ 2] = org1[2] + width * right1[2];
7122         vert[ 3] = org1[0] - width * right1[0];
7123         vert[ 4] = org1[1] - width * right1[1];
7124         vert[ 5] = org1[2] - width * right1[2];
7125         vert[ 6] = org2[0] - width * right2[0];
7126         vert[ 7] = org2[1] - width * right2[1];
7127         vert[ 8] = org2[2] - width * right2[2];
7128         vert[ 9] = org2[0] + width * right2[0];
7129         vert[10] = org2[1] + width * right2[1];
7130         vert[11] = org2[2] + width * right2[2];
7131 }
7132
7133 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)
7134 {
7135         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7136         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7137         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7138         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7139         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7140         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7141         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7142         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7143         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7144         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7145         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7146         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7147 }
7148
7149 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7150 {
7151         int i;
7152         float *vertex3f;
7153         float v[3];
7154         VectorSet(v, x, y, z);
7155         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7156                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7157                         break;
7158         if (i == mesh->numvertices)
7159         {
7160                 if (mesh->numvertices < mesh->maxvertices)
7161                 {
7162                         VectorCopy(v, vertex3f);
7163                         mesh->numvertices++;
7164                 }
7165                 return mesh->numvertices;
7166         }
7167         else
7168                 return i;
7169 }
7170
7171 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7172 {
7173         int i;
7174         int *e, element[3];
7175         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7176         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7177         e = mesh->element3i + mesh->numtriangles * 3;
7178         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7179         {
7180                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7181                 if (mesh->numtriangles < mesh->maxtriangles)
7182                 {
7183                         *e++ = element[0];
7184                         *e++ = element[1];
7185                         *e++ = element[2];
7186                         mesh->numtriangles++;
7187                 }
7188                 element[1] = element[2];
7189         }
7190 }
7191
7192 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7193 {
7194         int i;
7195         int *e, element[3];
7196         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7197         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7198         e = mesh->element3i + mesh->numtriangles * 3;
7199         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7200         {
7201                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7202                 if (mesh->numtriangles < mesh->maxtriangles)
7203                 {
7204                         *e++ = element[0];
7205                         *e++ = element[1];
7206                         *e++ = element[2];
7207                         mesh->numtriangles++;
7208                 }
7209                 element[1] = element[2];
7210         }
7211 }
7212
7213 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7214 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7215 {
7216         int planenum, planenum2;
7217         int w;
7218         int tempnumpoints;
7219         mplane_t *plane, *plane2;
7220         double maxdist;
7221         double temppoints[2][256*3];
7222         // figure out how large a bounding box we need to properly compute this brush
7223         maxdist = 0;
7224         for (w = 0;w < numplanes;w++)
7225                 maxdist = max(maxdist, fabs(planes[w].dist));
7226         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7227         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7228         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7229         {
7230                 w = 0;
7231                 tempnumpoints = 4;
7232                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7233                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7234                 {
7235                         if (planenum2 == planenum)
7236                                 continue;
7237                         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);
7238                         w = !w;
7239                 }
7240                 if (tempnumpoints < 3)
7241                         continue;
7242                 // generate elements forming a triangle fan for this polygon
7243                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7244         }
7245 }
7246
7247 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)
7248 {
7249         texturelayer_t *layer;
7250         layer = t->currentlayers + t->currentnumlayers++;
7251         layer->type = type;
7252         layer->depthmask = depthmask;
7253         layer->blendfunc1 = blendfunc1;
7254         layer->blendfunc2 = blendfunc2;
7255         layer->texture = texture;
7256         layer->texmatrix = *matrix;
7257         layer->color[0] = r;
7258         layer->color[1] = g;
7259         layer->color[2] = b;
7260         layer->color[3] = a;
7261 }
7262
7263 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7264 {
7265         if(parms[0] == 0 && parms[1] == 0)
7266                 return false;
7267         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7268                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7269                         return false;
7270         return true;
7271 }
7272
7273 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7274 {
7275         double index, f;
7276         index = parms[2] + r_refdef.scene.time * parms[3];
7277         index -= floor(index);
7278         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7279         {
7280         default:
7281         case Q3WAVEFUNC_NONE:
7282         case Q3WAVEFUNC_NOISE:
7283         case Q3WAVEFUNC_COUNT:
7284                 f = 0;
7285                 break;
7286         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7287         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7288         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7289         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7290         case Q3WAVEFUNC_TRIANGLE:
7291                 index *= 4;
7292                 f = index - floor(index);
7293                 if (index < 1)
7294                         f = f;
7295                 else if (index < 2)
7296                         f = 1 - f;
7297                 else if (index < 3)
7298                         f = -f;
7299                 else
7300                         f = -(1 - f);
7301                 break;
7302         }
7303         f = parms[0] + parms[1] * f;
7304         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7305                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7306         return (float) f;
7307 }
7308
7309 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7310 {
7311         int w, h, idx;
7312         float f;
7313         float tcmat[12];
7314         matrix4x4_t matrix, temp;
7315         switch(tcmod->tcmod)
7316         {
7317                 case Q3TCMOD_COUNT:
7318                 case Q3TCMOD_NONE:
7319                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7320                                 matrix = r_waterscrollmatrix;
7321                         else
7322                                 matrix = identitymatrix;
7323                         break;
7324                 case Q3TCMOD_ENTITYTRANSLATE:
7325                         // this is used in Q3 to allow the gamecode to control texcoord
7326                         // scrolling on the entity, which is not supported in darkplaces yet.
7327                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7328                         break;
7329                 case Q3TCMOD_ROTATE:
7330                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7331                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7332                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7333                         break;
7334                 case Q3TCMOD_SCALE:
7335                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7336                         break;
7337                 case Q3TCMOD_SCROLL:
7338                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7339                         break;
7340                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7341                         w = (int) tcmod->parms[0];
7342                         h = (int) tcmod->parms[1];
7343                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7344                         f = f - floor(f);
7345                         idx = (int) floor(f * w * h);
7346                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7347                         break;
7348                 case Q3TCMOD_STRETCH:
7349                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7350                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7351                         break;
7352                 case Q3TCMOD_TRANSFORM:
7353                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7354                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7355                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7356                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7357                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7358                         break;
7359                 case Q3TCMOD_TURBULENT:
7360                         // this is handled in the RSurf_PrepareVertices function
7361                         matrix = identitymatrix;
7362                         break;
7363         }
7364         temp = *texmatrix;
7365         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7366 }
7367
7368 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7369 {
7370         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7371         char name[MAX_QPATH];
7372         skinframe_t *skinframe;
7373         unsigned char pixels[296*194];
7374         strlcpy(cache->name, skinname, sizeof(cache->name));
7375         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7376         if (developer_loading.integer)
7377                 Con_Printf("loading %s\n", name);
7378         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7379         if (!skinframe || !skinframe->base)
7380         {
7381                 unsigned char *f;
7382                 fs_offset_t filesize;
7383                 skinframe = NULL;
7384                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7385                 if (f)
7386                 {
7387                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7388                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7389                         Mem_Free(f);
7390                 }
7391         }
7392         cache->skinframe = skinframe;
7393 }
7394
7395 texture_t *R_GetCurrentTexture(texture_t *t)
7396 {
7397         int i;
7398         const entity_render_t *ent = rsurface.entity;
7399         dp_model_t *model = ent->model;
7400         q3shaderinfo_layer_tcmod_t *tcmod;
7401
7402         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7403                 return t->currentframe;
7404         t->update_lastrenderframe = r_textureframe;
7405         t->update_lastrenderentity = (void *)ent;
7406
7407         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7408                 t->camera_entity = ent->entitynumber;
7409         else
7410                 t->camera_entity = 0;
7411
7412         // switch to an alternate material if this is a q1bsp animated material
7413         {
7414                 texture_t *texture = t;
7415                 int s = rsurface.ent_skinnum;
7416                 if ((unsigned int)s >= (unsigned int)model->numskins)
7417                         s = 0;
7418                 if (model->skinscenes)
7419                 {
7420                         if (model->skinscenes[s].framecount > 1)
7421                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7422                         else
7423                                 s = model->skinscenes[s].firstframe;
7424                 }
7425                 if (s > 0)
7426                         t = t + s * model->num_surfaces;
7427                 if (t->animated)
7428                 {
7429                         // use an alternate animation if the entity's frame is not 0,
7430                         // and only if the texture has an alternate animation
7431                         if (rsurface.ent_alttextures && t->anim_total[1])
7432                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7433                         else
7434                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7435                 }
7436                 texture->currentframe = t;
7437         }
7438
7439         // update currentskinframe to be a qw skin or animation frame
7440         if (rsurface.ent_qwskin >= 0)
7441         {
7442                 i = rsurface.ent_qwskin;
7443                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7444                 {
7445                         r_qwskincache_size = cl.maxclients;
7446                         if (r_qwskincache)
7447                                 Mem_Free(r_qwskincache);
7448                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7449                 }
7450                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7451                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7452                 t->currentskinframe = r_qwskincache[i].skinframe;
7453                 if (t->currentskinframe == NULL)
7454                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7455         }
7456         else if (t->numskinframes >= 2)
7457                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7458         if (t->backgroundnumskinframes >= 2)
7459                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7460
7461         t->currentmaterialflags = t->basematerialflags;
7462         t->currentalpha = rsurface.colormod[3];
7463         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7464                 t->currentalpha *= r_wateralpha.value;
7465         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7466                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7467         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7468                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7469         if (!(rsurface.ent_flags & RENDER_LIGHT))
7470                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7471         else if (FAKELIGHT_ENABLED)
7472         {
7473                         // no modellight if using fakelight for the map
7474         }
7475         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7476         {
7477                 // pick a model lighting mode
7478                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7479                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7480                 else
7481                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7482         }
7483         if (rsurface.ent_flags & RENDER_ADDITIVE)
7484                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7485         else if (t->currentalpha < 1)
7486                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7487         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7488                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7489         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7490                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7491         if (t->backgroundnumskinframes)
7492                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7493         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7494         {
7495                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7496                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7497         }
7498         else
7499                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7500         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7501                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7502
7503         // there is no tcmod
7504         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7505         {
7506                 t->currenttexmatrix = r_waterscrollmatrix;
7507                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7508         }
7509         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7510         {
7511                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7512                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7513         }
7514
7515         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7516                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7517         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7518                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7519
7520         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7521         if (t->currentskinframe->qpixels)
7522                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7523         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7524         if (!t->basetexture)
7525                 t->basetexture = r_texture_notexture;
7526         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7527         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7528         t->nmaptexture = t->currentskinframe->nmap;
7529         if (!t->nmaptexture)
7530                 t->nmaptexture = r_texture_blanknormalmap;
7531         t->glosstexture = r_texture_black;
7532         t->glowtexture = t->currentskinframe->glow;
7533         t->fogtexture = t->currentskinframe->fog;
7534         t->reflectmasktexture = t->currentskinframe->reflect;
7535         if (t->backgroundnumskinframes)
7536         {
7537                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7538                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7539                 t->backgroundglosstexture = r_texture_black;
7540                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7541                 if (!t->backgroundnmaptexture)
7542                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7543         }
7544         else
7545         {
7546                 t->backgroundbasetexture = r_texture_white;
7547                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7548                 t->backgroundglosstexture = r_texture_black;
7549                 t->backgroundglowtexture = NULL;
7550         }
7551         t->specularpower = r_shadow_glossexponent.value;
7552         // TODO: store reference values for these in the texture?
7553         t->specularscale = 0;
7554         if (r_shadow_gloss.integer > 0)
7555         {
7556                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7557                 {
7558                         if (r_shadow_glossintensity.value > 0)
7559                         {
7560                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7561                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7562                                 t->specularscale = r_shadow_glossintensity.value;
7563                         }
7564                 }
7565                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7566                 {
7567                         t->glosstexture = r_texture_white;
7568                         t->backgroundglosstexture = r_texture_white;
7569                         t->specularscale = r_shadow_gloss2intensity.value;
7570                         t->specularpower = r_shadow_gloss2exponent.value;
7571                 }
7572         }
7573         t->specularscale *= t->specularscalemod;
7574         t->specularpower *= t->specularpowermod;
7575
7576         // lightmaps mode looks bad with dlights using actual texturing, so turn
7577         // off the colormap and glossmap, but leave the normalmap on as it still
7578         // accurately represents the shading involved
7579         if (gl_lightmaps.integer)
7580         {
7581                 t->basetexture = r_texture_grey128;
7582                 t->pantstexture = r_texture_black;
7583                 t->shirttexture = r_texture_black;
7584                 t->nmaptexture = r_texture_blanknormalmap;
7585                 t->glosstexture = r_texture_black;
7586                 t->glowtexture = NULL;
7587                 t->fogtexture = NULL;
7588                 t->reflectmasktexture = NULL;
7589                 t->backgroundbasetexture = NULL;
7590                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7591                 t->backgroundglosstexture = r_texture_black;
7592                 t->backgroundglowtexture = NULL;
7593                 t->specularscale = 0;
7594                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7595         }
7596
7597         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7598         VectorClear(t->dlightcolor);
7599         t->currentnumlayers = 0;
7600         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7601         {
7602                 int blendfunc1, blendfunc2;
7603                 qboolean depthmask;
7604                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7605                 {
7606                         blendfunc1 = GL_SRC_ALPHA;
7607                         blendfunc2 = GL_ONE;
7608                 }
7609                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7610                 {
7611                         blendfunc1 = GL_SRC_ALPHA;
7612                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7613                 }
7614                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7615                 {
7616                         blendfunc1 = t->customblendfunc[0];
7617                         blendfunc2 = t->customblendfunc[1];
7618                 }
7619                 else
7620                 {
7621                         blendfunc1 = GL_ONE;
7622                         blendfunc2 = GL_ZERO;
7623                 }
7624                 // don't colormod evilblend textures
7625                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7626                         VectorSet(t->lightmapcolor, 1, 1, 1);
7627                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7628                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7629                 {
7630                         // fullbright is not affected by r_refdef.lightmapintensity
7631                         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]);
7632                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7633                                 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]);
7634                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7635                                 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]);
7636                 }
7637                 else
7638                 {
7639                         vec3_t ambientcolor;
7640                         float colorscale;
7641                         // set the color tint used for lights affecting this surface
7642                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7643                         colorscale = 2;
7644                         // q3bsp has no lightmap updates, so the lightstylevalue that
7645                         // would normally be baked into the lightmap must be
7646                         // applied to the color
7647                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7648                         if (model->type == mod_brushq3)
7649                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7650                         colorscale *= r_refdef.lightmapintensity;
7651                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7652                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7653                         // basic lit geometry
7654                         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]);
7655                         // add pants/shirt if needed
7656                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7657                                 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]);
7658                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7659                                 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]);
7660                         // now add ambient passes if needed
7661                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7662                         {
7663                                 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]);
7664                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7665                                         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]);
7666                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7667                                         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]);
7668                         }
7669                 }
7670                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7671                         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]);
7672                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7673                 {
7674                         // if this is opaque use alpha blend which will darken the earlier
7675                         // passes cheaply.
7676                         //
7677                         // if this is an alpha blended material, all the earlier passes
7678                         // were darkened by fog already, so we only need to add the fog
7679                         // color ontop through the fog mask texture
7680                         //
7681                         // if this is an additive blended material, all the earlier passes
7682                         // were darkened by fog already, and we should not add fog color
7683                         // (because the background was not darkened, there is no fog color
7684                         // that was lost behind it).
7685                         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]);
7686                 }
7687         }
7688
7689         return t->currentframe;
7690 }
7691
7692 rsurfacestate_t rsurface;
7693
7694 void RSurf_ActiveWorldEntity(void)
7695 {
7696         dp_model_t *model = r_refdef.scene.worldmodel;
7697         //if (rsurface.entity == r_refdef.scene.worldentity)
7698         //      return;
7699         rsurface.entity = r_refdef.scene.worldentity;
7700         rsurface.skeleton = NULL;
7701         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7702         rsurface.ent_skinnum = 0;
7703         rsurface.ent_qwskin = -1;
7704         rsurface.ent_shadertime = 0;
7705         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7706         rsurface.matrix = identitymatrix;
7707         rsurface.inversematrix = identitymatrix;
7708         rsurface.matrixscale = 1;
7709         rsurface.inversematrixscale = 1;
7710         R_EntityMatrix(&identitymatrix);
7711         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7712         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7713         rsurface.fograngerecip = r_refdef.fograngerecip;
7714         rsurface.fogheightfade = r_refdef.fogheightfade;
7715         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7716         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7717         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7718         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7719         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7720         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7721         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7722         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7723         rsurface.colormod[3] = 1;
7724         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);
7725         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7726         rsurface.frameblend[0].lerp = 1;
7727         rsurface.ent_alttextures = false;
7728         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7729         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7730         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7731         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7732         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7733         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7734         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7735         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7736         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7737         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7738         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7739         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7740         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7741         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7742         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7743         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7744         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7745         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7746         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7747         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7748         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7749         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7750         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7751         rsurface.modelelement3i = model->surfmesh.data_element3i;
7752         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7753         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7754         rsurface.modelelement3s = model->surfmesh.data_element3s;
7755         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7756         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7757         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7758         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7759         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7760         rsurface.modelsurfaces = model->data_surfaces;
7761         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7762         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7763         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7764         rsurface.modelgeneratedvertex = false;
7765         rsurface.batchgeneratedvertex = false;
7766         rsurface.batchfirstvertex = 0;
7767         rsurface.batchnumvertices = 0;
7768         rsurface.batchfirsttriangle = 0;
7769         rsurface.batchnumtriangles = 0;
7770         rsurface.batchvertex3f  = NULL;
7771         rsurface.batchvertex3f_vertexbuffer = NULL;
7772         rsurface.batchvertex3f_bufferoffset = 0;
7773         rsurface.batchsvector3f = NULL;
7774         rsurface.batchsvector3f_vertexbuffer = NULL;
7775         rsurface.batchsvector3f_bufferoffset = 0;
7776         rsurface.batchtvector3f = NULL;
7777         rsurface.batchtvector3f_vertexbuffer = NULL;
7778         rsurface.batchtvector3f_bufferoffset = 0;
7779         rsurface.batchnormal3f  = NULL;
7780         rsurface.batchnormal3f_vertexbuffer = NULL;
7781         rsurface.batchnormal3f_bufferoffset = 0;
7782         rsurface.batchlightmapcolor4f = NULL;
7783         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7784         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7785         rsurface.batchtexcoordtexture2f = NULL;
7786         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7787         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7788         rsurface.batchtexcoordlightmap2f = NULL;
7789         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7790         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7791         rsurface.batchvertexmesh = NULL;
7792         rsurface.batchvertexmeshbuffer = NULL;
7793         rsurface.batchvertex3fbuffer = NULL;
7794         rsurface.batchelement3i = NULL;
7795         rsurface.batchelement3i_indexbuffer = NULL;
7796         rsurface.batchelement3i_bufferoffset = 0;
7797         rsurface.batchelement3s = NULL;
7798         rsurface.batchelement3s_indexbuffer = NULL;
7799         rsurface.batchelement3s_bufferoffset = 0;
7800         rsurface.passcolor4f = NULL;
7801         rsurface.passcolor4f_vertexbuffer = NULL;
7802         rsurface.passcolor4f_bufferoffset = 0;
7803 }
7804
7805 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7806 {
7807         dp_model_t *model = ent->model;
7808         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7809         //      return;
7810         rsurface.entity = (entity_render_t *)ent;
7811         rsurface.skeleton = ent->skeleton;
7812         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7813         rsurface.ent_skinnum = ent->skinnum;
7814         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;
7815         rsurface.ent_shadertime = ent->shadertime;
7816         rsurface.ent_flags = ent->flags;
7817         rsurface.matrix = ent->matrix;
7818         rsurface.inversematrix = ent->inversematrix;
7819         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7820         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7821         R_EntityMatrix(&rsurface.matrix);
7822         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7823         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7824         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7825         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7826         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7827         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7828         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7829         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7830         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7831         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7832         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7833         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7834         rsurface.colormod[3] = ent->alpha;
7835         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7836         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7837         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7838         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7839         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7840         if (ent->model->brush.submodel && !prepass)
7841         {
7842                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7843                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7844         }
7845         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7846         {
7847                 if (ent->animcache_vertex3f)
7848                 {
7849                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7850                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7851                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7852                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7853                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7854                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7855                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7856                 }
7857                 else if (wanttangents)
7858                 {
7859                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7860                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7861                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7862                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7863                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7864                         rsurface.modelvertexmesh = NULL;
7865                         rsurface.modelvertexmeshbuffer = NULL;
7866                         rsurface.modelvertex3fbuffer = NULL;
7867                 }
7868                 else if (wantnormals)
7869                 {
7870                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7871                         rsurface.modelsvector3f = NULL;
7872                         rsurface.modeltvector3f = NULL;
7873                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7874                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7875                         rsurface.modelvertexmesh = NULL;
7876                         rsurface.modelvertexmeshbuffer = NULL;
7877                         rsurface.modelvertex3fbuffer = NULL;
7878                 }
7879                 else
7880                 {
7881                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7882                         rsurface.modelsvector3f = NULL;
7883                         rsurface.modeltvector3f = NULL;
7884                         rsurface.modelnormal3f = NULL;
7885                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7886                         rsurface.modelvertexmesh = NULL;
7887                         rsurface.modelvertexmeshbuffer = NULL;
7888                         rsurface.modelvertex3fbuffer = NULL;
7889                 }
7890                 rsurface.modelvertex3f_vertexbuffer = 0;
7891                 rsurface.modelvertex3f_bufferoffset = 0;
7892                 rsurface.modelsvector3f_vertexbuffer = 0;
7893                 rsurface.modelsvector3f_bufferoffset = 0;
7894                 rsurface.modeltvector3f_vertexbuffer = 0;
7895                 rsurface.modeltvector3f_bufferoffset = 0;
7896                 rsurface.modelnormal3f_vertexbuffer = 0;
7897                 rsurface.modelnormal3f_bufferoffset = 0;
7898                 rsurface.modelgeneratedvertex = true;
7899         }
7900         else
7901         {
7902                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7903                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7904                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7905                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7906                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7907                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7908                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7909                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7910                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7911                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7912                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7913                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7914                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7915                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7916                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7917                 rsurface.modelgeneratedvertex = false;
7918         }
7919         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7920         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7921         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7922         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7923         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7924         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7925         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7926         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7927         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7928         rsurface.modelelement3i = model->surfmesh.data_element3i;
7929         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7930         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7931         rsurface.modelelement3s = model->surfmesh.data_element3s;
7932         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7933         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7934         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7935         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7936         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7937         rsurface.modelsurfaces = model->data_surfaces;
7938         rsurface.batchgeneratedvertex = false;
7939         rsurface.batchfirstvertex = 0;
7940         rsurface.batchnumvertices = 0;
7941         rsurface.batchfirsttriangle = 0;
7942         rsurface.batchnumtriangles = 0;
7943         rsurface.batchvertex3f  = NULL;
7944         rsurface.batchvertex3f_vertexbuffer = NULL;
7945         rsurface.batchvertex3f_bufferoffset = 0;
7946         rsurface.batchsvector3f = NULL;
7947         rsurface.batchsvector3f_vertexbuffer = NULL;
7948         rsurface.batchsvector3f_bufferoffset = 0;
7949         rsurface.batchtvector3f = NULL;
7950         rsurface.batchtvector3f_vertexbuffer = NULL;
7951         rsurface.batchtvector3f_bufferoffset = 0;
7952         rsurface.batchnormal3f  = NULL;
7953         rsurface.batchnormal3f_vertexbuffer = NULL;
7954         rsurface.batchnormal3f_bufferoffset = 0;
7955         rsurface.batchlightmapcolor4f = NULL;
7956         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7957         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7958         rsurface.batchtexcoordtexture2f = NULL;
7959         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7960         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7961         rsurface.batchtexcoordlightmap2f = NULL;
7962         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7963         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7964         rsurface.batchvertexmesh = NULL;
7965         rsurface.batchvertexmeshbuffer = NULL;
7966         rsurface.batchvertex3fbuffer = NULL;
7967         rsurface.batchelement3i = NULL;
7968         rsurface.batchelement3i_indexbuffer = NULL;
7969         rsurface.batchelement3i_bufferoffset = 0;
7970         rsurface.batchelement3s = NULL;
7971         rsurface.batchelement3s_indexbuffer = NULL;
7972         rsurface.batchelement3s_bufferoffset = 0;
7973         rsurface.passcolor4f = NULL;
7974         rsurface.passcolor4f_vertexbuffer = NULL;
7975         rsurface.passcolor4f_bufferoffset = 0;
7976 }
7977
7978 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)
7979 {
7980         rsurface.entity = r_refdef.scene.worldentity;
7981         rsurface.skeleton = NULL;
7982         rsurface.ent_skinnum = 0;
7983         rsurface.ent_qwskin = -1;
7984         rsurface.ent_shadertime = shadertime;
7985         rsurface.ent_flags = entflags;
7986         rsurface.modelnumvertices = numvertices;
7987         rsurface.modelnumtriangles = numtriangles;
7988         rsurface.matrix = *matrix;
7989         rsurface.inversematrix = *inversematrix;
7990         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7991         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7992         R_EntityMatrix(&rsurface.matrix);
7993         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7994         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7995         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7996         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7997         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7998         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7999         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8000         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8001         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8002         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8003         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8004         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8005         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);
8006         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8007         rsurface.frameblend[0].lerp = 1;
8008         rsurface.ent_alttextures = false;
8009         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8010         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8011         if (wanttangents)
8012         {
8013                 rsurface.modelvertex3f = (float *)vertex3f;
8014                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8015                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8016                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8017         }
8018         else if (wantnormals)
8019         {
8020                 rsurface.modelvertex3f = (float *)vertex3f;
8021                 rsurface.modelsvector3f = NULL;
8022                 rsurface.modeltvector3f = NULL;
8023                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8024         }
8025         else
8026         {
8027                 rsurface.modelvertex3f = (float *)vertex3f;
8028                 rsurface.modelsvector3f = NULL;
8029                 rsurface.modeltvector3f = NULL;
8030                 rsurface.modelnormal3f = NULL;
8031         }
8032         rsurface.modelvertexmesh = NULL;
8033         rsurface.modelvertexmeshbuffer = NULL;
8034         rsurface.modelvertex3fbuffer = NULL;
8035         rsurface.modelvertex3f_vertexbuffer = 0;
8036         rsurface.modelvertex3f_bufferoffset = 0;
8037         rsurface.modelsvector3f_vertexbuffer = 0;
8038         rsurface.modelsvector3f_bufferoffset = 0;
8039         rsurface.modeltvector3f_vertexbuffer = 0;
8040         rsurface.modeltvector3f_bufferoffset = 0;
8041         rsurface.modelnormal3f_vertexbuffer = 0;
8042         rsurface.modelnormal3f_bufferoffset = 0;
8043         rsurface.modelgeneratedvertex = true;
8044         rsurface.modellightmapcolor4f  = (float *)color4f;
8045         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8046         rsurface.modellightmapcolor4f_bufferoffset = 0;
8047         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8048         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8049         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8050         rsurface.modeltexcoordlightmap2f  = NULL;
8051         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8052         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8053         rsurface.modelelement3i = (int *)element3i;
8054         rsurface.modelelement3i_indexbuffer = NULL;
8055         rsurface.modelelement3i_bufferoffset = 0;
8056         rsurface.modelelement3s = (unsigned short *)element3s;
8057         rsurface.modelelement3s_indexbuffer = NULL;
8058         rsurface.modelelement3s_bufferoffset = 0;
8059         rsurface.modellightmapoffsets = NULL;
8060         rsurface.modelsurfaces = NULL;
8061         rsurface.batchgeneratedvertex = false;
8062         rsurface.batchfirstvertex = 0;
8063         rsurface.batchnumvertices = 0;
8064         rsurface.batchfirsttriangle = 0;
8065         rsurface.batchnumtriangles = 0;
8066         rsurface.batchvertex3f  = NULL;
8067         rsurface.batchvertex3f_vertexbuffer = NULL;
8068         rsurface.batchvertex3f_bufferoffset = 0;
8069         rsurface.batchsvector3f = NULL;
8070         rsurface.batchsvector3f_vertexbuffer = NULL;
8071         rsurface.batchsvector3f_bufferoffset = 0;
8072         rsurface.batchtvector3f = NULL;
8073         rsurface.batchtvector3f_vertexbuffer = NULL;
8074         rsurface.batchtvector3f_bufferoffset = 0;
8075         rsurface.batchnormal3f  = NULL;
8076         rsurface.batchnormal3f_vertexbuffer = NULL;
8077         rsurface.batchnormal3f_bufferoffset = 0;
8078         rsurface.batchlightmapcolor4f = NULL;
8079         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8080         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8081         rsurface.batchtexcoordtexture2f = NULL;
8082         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8083         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8084         rsurface.batchtexcoordlightmap2f = NULL;
8085         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8086         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8087         rsurface.batchvertexmesh = NULL;
8088         rsurface.batchvertexmeshbuffer = NULL;
8089         rsurface.batchvertex3fbuffer = NULL;
8090         rsurface.batchelement3i = NULL;
8091         rsurface.batchelement3i_indexbuffer = NULL;
8092         rsurface.batchelement3i_bufferoffset = 0;
8093         rsurface.batchelement3s = NULL;
8094         rsurface.batchelement3s_indexbuffer = NULL;
8095         rsurface.batchelement3s_bufferoffset = 0;
8096         rsurface.passcolor4f = NULL;
8097         rsurface.passcolor4f_vertexbuffer = NULL;
8098         rsurface.passcolor4f_bufferoffset = 0;
8099
8100         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8101         {
8102                 if ((wantnormals || wanttangents) && !normal3f)
8103                 {
8104                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8105                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8106                 }
8107                 if (wanttangents && !svector3f)
8108                 {
8109                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8110                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8111                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8112                 }
8113         }
8114 }
8115
8116 float RSurf_FogPoint(const float *v)
8117 {
8118         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8119         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8120         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8121         float FogHeightFade = r_refdef.fogheightfade;
8122         float fogfrac;
8123         unsigned int fogmasktableindex;
8124         if (r_refdef.fogplaneviewabove)
8125                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8126         else
8127                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8128         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8129         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8130 }
8131
8132 float RSurf_FogVertex(const float *v)
8133 {
8134         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8135         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8136         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8137         float FogHeightFade = rsurface.fogheightfade;
8138         float fogfrac;
8139         unsigned int fogmasktableindex;
8140         if (r_refdef.fogplaneviewabove)
8141                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8142         else
8143                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8144         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8145         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8146 }
8147
8148 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8149 {
8150         int i;
8151         for (i = 0;i < numelements;i++)
8152                 outelement3i[i] = inelement3i[i] + adjust;
8153 }
8154
8155 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8156 extern cvar_t gl_vbo;
8157 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8158 {
8159         int deformindex;
8160         int firsttriangle;
8161         int numtriangles;
8162         int firstvertex;
8163         int endvertex;
8164         int numvertices;
8165         int surfacefirsttriangle;
8166         int surfacenumtriangles;
8167         int surfacefirstvertex;
8168         int surfaceendvertex;
8169         int surfacenumvertices;
8170         int batchnumvertices;
8171         int batchnumtriangles;
8172         int needsupdate;
8173         int i, j;
8174         qboolean gaps;
8175         qboolean dynamicvertex;
8176         float amplitude;
8177         float animpos;
8178         float scale;
8179         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8180         float waveparms[4];
8181         q3shaderinfo_deform_t *deform;
8182         const msurface_t *surface, *firstsurface;
8183         r_vertexmesh_t *vertexmesh;
8184         if (!texturenumsurfaces)
8185                 return;
8186         // find vertex range of this surface batch
8187         gaps = false;
8188         firstsurface = texturesurfacelist[0];
8189         firsttriangle = firstsurface->num_firsttriangle;
8190         batchnumvertices = 0;
8191         batchnumtriangles = 0;
8192         firstvertex = endvertex = firstsurface->num_firstvertex;
8193         for (i = 0;i < texturenumsurfaces;i++)
8194         {
8195                 surface = texturesurfacelist[i];
8196                 if (surface != firstsurface + i)
8197                         gaps = true;
8198                 surfacefirstvertex = surface->num_firstvertex;
8199                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8200                 surfacenumvertices = surface->num_vertices;
8201                 surfacenumtriangles = surface->num_triangles;
8202                 if (firstvertex > surfacefirstvertex)
8203                         firstvertex = surfacefirstvertex;
8204                 if (endvertex < surfaceendvertex)
8205                         endvertex = surfaceendvertex;
8206                 batchnumvertices += surfacenumvertices;
8207                 batchnumtriangles += surfacenumtriangles;
8208         }
8209
8210         // we now know the vertex range used, and if there are any gaps in it
8211         rsurface.batchfirstvertex = firstvertex;
8212         rsurface.batchnumvertices = endvertex - firstvertex;
8213         rsurface.batchfirsttriangle = firsttriangle;
8214         rsurface.batchnumtriangles = batchnumtriangles;
8215
8216         // this variable holds flags for which properties have been updated that
8217         // may require regenerating vertexmesh array...
8218         needsupdate = 0;
8219
8220         // check if any dynamic vertex processing must occur
8221         dynamicvertex = false;
8222
8223         // if there is a chance of animated vertex colors, it's a dynamic batch
8224         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8225         {
8226                 dynamicvertex = true;
8227                 batchneed |= BATCHNEED_NOGAPS;
8228                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8229         }
8230
8231         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8232         {
8233                 switch (deform->deform)
8234                 {
8235                 default:
8236                 case Q3DEFORM_PROJECTIONSHADOW:
8237                 case Q3DEFORM_TEXT0:
8238                 case Q3DEFORM_TEXT1:
8239                 case Q3DEFORM_TEXT2:
8240                 case Q3DEFORM_TEXT3:
8241                 case Q3DEFORM_TEXT4:
8242                 case Q3DEFORM_TEXT5:
8243                 case Q3DEFORM_TEXT6:
8244                 case Q3DEFORM_TEXT7:
8245                 case Q3DEFORM_NONE:
8246                         break;
8247                 case Q3DEFORM_AUTOSPRITE:
8248                         dynamicvertex = true;
8249                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8250                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8251                         break;
8252                 case Q3DEFORM_AUTOSPRITE2:
8253                         dynamicvertex = true;
8254                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8255                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8256                         break;
8257                 case Q3DEFORM_NORMAL:
8258                         dynamicvertex = true;
8259                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8260                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8261                         break;
8262                 case Q3DEFORM_WAVE:
8263                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8264                                 break; // if wavefunc is a nop, ignore this transform
8265                         dynamicvertex = true;
8266                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8267                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8268                         break;
8269                 case Q3DEFORM_BULGE:
8270                         dynamicvertex = true;
8271                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8272                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8273                         break;
8274                 case Q3DEFORM_MOVE:
8275                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8276                                 break; // if wavefunc is a nop, ignore this transform
8277                         dynamicvertex = true;
8278                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8279                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8280                         break;
8281                 }
8282         }
8283         switch(rsurface.texture->tcgen.tcgen)
8284         {
8285         default:
8286         case Q3TCGEN_TEXTURE:
8287                 break;
8288         case Q3TCGEN_LIGHTMAP:
8289                 dynamicvertex = true;
8290                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8291                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8292                 break;
8293         case Q3TCGEN_VECTOR:
8294                 dynamicvertex = true;
8295                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8296                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8297                 break;
8298         case Q3TCGEN_ENVIRONMENT:
8299                 dynamicvertex = true;
8300                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8301                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8302                 break;
8303         }
8304         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8305         {
8306                 dynamicvertex = true;
8307                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8308                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8309         }
8310
8311         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8312         {
8313                 dynamicvertex = true;
8314                 batchneed |= BATCHNEED_NOGAPS;
8315                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8316         }
8317
8318         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8319         {
8320                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8321                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8322                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8323                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8324                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8325                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8326                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8327         }
8328
8329         // when the model data has no vertex buffer (dynamic mesh), we need to
8330         // eliminate gaps
8331         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8332                 batchneed |= BATCHNEED_NOGAPS;
8333
8334         // if needsupdate, we have to do a dynamic vertex batch for sure
8335         if (needsupdate & batchneed)
8336                 dynamicvertex = true;
8337
8338         // see if we need to build vertexmesh from arrays
8339         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8340                 dynamicvertex = true;
8341
8342         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8343         // also some drivers strongly dislike firstvertex
8344         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8345                 dynamicvertex = true;
8346
8347         rsurface.batchvertex3f = rsurface.modelvertex3f;
8348         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8349         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8350         rsurface.batchsvector3f = rsurface.modelsvector3f;
8351         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8352         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8353         rsurface.batchtvector3f = rsurface.modeltvector3f;
8354         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8355         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8356         rsurface.batchnormal3f = rsurface.modelnormal3f;
8357         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8358         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8359         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8360         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8361         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8362         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8363         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8364         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8365         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8366         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8367         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8368         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8369         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8370         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8371         rsurface.batchelement3i = rsurface.modelelement3i;
8372         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8373         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8374         rsurface.batchelement3s = rsurface.modelelement3s;
8375         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8376         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8377
8378         // if any dynamic vertex processing has to occur in software, we copy the
8379         // entire surface list together before processing to rebase the vertices
8380         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8381         //
8382         // if any gaps exist and we do not have a static vertex buffer, we have to
8383         // copy the surface list together to avoid wasting upload bandwidth on the
8384         // vertices in the gaps.
8385         //
8386         // if gaps exist and we have a static vertex buffer, we still have to
8387         // combine the index buffer ranges into one dynamic index buffer.
8388         //
8389         // in all cases we end up with data that can be drawn in one call.
8390
8391         if (!dynamicvertex)
8392         {
8393                 // static vertex data, just set pointers...
8394                 rsurface.batchgeneratedvertex = false;
8395                 // if there are gaps, we want to build a combined index buffer,
8396                 // otherwise use the original static buffer with an appropriate offset
8397                 if (gaps)
8398                 {
8399                         // build a new triangle elements array for this batch
8400                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8401                         rsurface.batchfirsttriangle = 0;
8402                         numtriangles = 0;
8403                         for (i = 0;i < texturenumsurfaces;i++)
8404                         {
8405                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8406                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8407                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8408                                 numtriangles += surfacenumtriangles;
8409                         }
8410                         rsurface.batchelement3i_indexbuffer = NULL;
8411                         rsurface.batchelement3i_bufferoffset = 0;
8412                         rsurface.batchelement3s = NULL;
8413                         rsurface.batchelement3s_indexbuffer = NULL;
8414                         rsurface.batchelement3s_bufferoffset = 0;
8415                         if (endvertex <= 65536)
8416                         {
8417                                 // make a 16bit (unsigned short) index array if possible
8418                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8419                                 for (i = 0;i < numtriangles*3;i++)
8420                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8421                         }
8422                 }
8423                 return;
8424         }
8425
8426         // something needs software processing, do it for real...
8427         // we only directly handle separate array data in this case and then
8428         // generate interleaved data if needed...
8429         rsurface.batchgeneratedvertex = true;
8430
8431         // now copy the vertex data into a combined array and make an index array
8432         // (this is what Quake3 does all the time)
8433         //if (gaps || rsurface.batchfirstvertex)
8434         {
8435                 rsurface.batchvertex3fbuffer = NULL;
8436                 rsurface.batchvertexmesh = NULL;
8437                 rsurface.batchvertexmeshbuffer = NULL;
8438                 rsurface.batchvertex3f = NULL;
8439                 rsurface.batchvertex3f_vertexbuffer = NULL;
8440                 rsurface.batchvertex3f_bufferoffset = 0;
8441                 rsurface.batchsvector3f = NULL;
8442                 rsurface.batchsvector3f_vertexbuffer = NULL;
8443                 rsurface.batchsvector3f_bufferoffset = 0;
8444                 rsurface.batchtvector3f = NULL;
8445                 rsurface.batchtvector3f_vertexbuffer = NULL;
8446                 rsurface.batchtvector3f_bufferoffset = 0;
8447                 rsurface.batchnormal3f = NULL;
8448                 rsurface.batchnormal3f_vertexbuffer = NULL;
8449                 rsurface.batchnormal3f_bufferoffset = 0;
8450                 rsurface.batchlightmapcolor4f = NULL;
8451                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8452                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8453                 rsurface.batchtexcoordtexture2f = NULL;
8454                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8455                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8456                 rsurface.batchtexcoordlightmap2f = NULL;
8457                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8458                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8459                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8460                 rsurface.batchelement3i_indexbuffer = NULL;
8461                 rsurface.batchelement3i_bufferoffset = 0;
8462                 rsurface.batchelement3s = NULL;
8463                 rsurface.batchelement3s_indexbuffer = NULL;
8464                 rsurface.batchelement3s_bufferoffset = 0;
8465                 // we'll only be setting up certain arrays as needed
8466                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8467                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8468                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8469                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8470                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8471                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8472                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8473                 {
8474                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8475                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8476                 }
8477                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8478                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8479                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8480                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8481                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8482                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8483                 numvertices = 0;
8484                 numtriangles = 0;
8485                 for (i = 0;i < texturenumsurfaces;i++)
8486                 {
8487                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8488                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8489                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8490                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8491                         // copy only the data requested
8492                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8493                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8494                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8495                         {
8496                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8497                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8498                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8499                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8500                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8501                                 {
8502                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8503                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8504                                 }
8505                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8506                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8507                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8508                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8509                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8510                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8511                         }
8512                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8513                         numvertices += surfacenumvertices;
8514                         numtriangles += surfacenumtriangles;
8515                 }
8516
8517                 // generate a 16bit index array as well if possible
8518                 // (in general, dynamic batches fit)
8519                 if (numvertices <= 65536)
8520                 {
8521                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8522                         for (i = 0;i < numtriangles*3;i++)
8523                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8524                 }
8525
8526                 // since we've copied everything, the batch now starts at 0
8527                 rsurface.batchfirstvertex = 0;
8528                 rsurface.batchnumvertices = batchnumvertices;
8529                 rsurface.batchfirsttriangle = 0;
8530                 rsurface.batchnumtriangles = batchnumtriangles;
8531         }
8532
8533         // q1bsp surfaces rendered in vertex color mode have to have colors
8534         // calculated based on lightstyles
8535         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8536         {
8537                 // generate color arrays for the surfaces in this list
8538                 int c[4];
8539                 int scale;
8540                 int size3;
8541                 const int *offsets;
8542                 const unsigned char *lm;
8543                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8544                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8545                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8546                 numvertices = 0;
8547                 for (i = 0;i < texturenumsurfaces;i++)
8548                 {
8549                         surface = texturesurfacelist[i];
8550                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8551                         surfacenumvertices = surface->num_vertices;
8552                         if (surface->lightmapinfo->samples)
8553                         {
8554                                 for (j = 0;j < surfacenumvertices;j++)
8555                                 {
8556                                         lm = surface->lightmapinfo->samples + offsets[j];
8557                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8558                                         VectorScale(lm, scale, c);
8559                                         if (surface->lightmapinfo->styles[1] != 255)
8560                                         {
8561                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8562                                                 lm += size3;
8563                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8564                                                 VectorMA(c, scale, lm, c);
8565                                                 if (surface->lightmapinfo->styles[2] != 255)
8566                                                 {
8567                                                         lm += size3;
8568                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8569                                                         VectorMA(c, scale, lm, c);
8570                                                         if (surface->lightmapinfo->styles[3] != 255)
8571                                                         {
8572                                                                 lm += size3;
8573                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8574                                                                 VectorMA(c, scale, lm, c);
8575                                                         }
8576                                                 }
8577                                         }
8578                                         c[0] >>= 7;
8579                                         c[1] >>= 7;
8580                                         c[2] >>= 7;
8581                                         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);
8582                                         numvertices++;
8583                                 }
8584                         }
8585                         else
8586                         {
8587                                 for (j = 0;j < surfacenumvertices;j++)
8588                                 {
8589                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8590                                         numvertices++;
8591                                 }
8592                         }
8593                 }
8594         }
8595
8596         // if vertices are deformed (sprite flares and things in maps, possibly
8597         // water waves, bulges and other deformations), modify the copied vertices
8598         // in place
8599         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8600         {
8601                 switch (deform->deform)
8602                 {
8603                 default:
8604                 case Q3DEFORM_PROJECTIONSHADOW:
8605                 case Q3DEFORM_TEXT0:
8606                 case Q3DEFORM_TEXT1:
8607                 case Q3DEFORM_TEXT2:
8608                 case Q3DEFORM_TEXT3:
8609                 case Q3DEFORM_TEXT4:
8610                 case Q3DEFORM_TEXT5:
8611                 case Q3DEFORM_TEXT6:
8612                 case Q3DEFORM_TEXT7:
8613                 case Q3DEFORM_NONE:
8614                         break;
8615                 case Q3DEFORM_AUTOSPRITE:
8616                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8617                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8618                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8619                         VectorNormalize(newforward);
8620                         VectorNormalize(newright);
8621                         VectorNormalize(newup);
8622 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8623 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8624 //                      rsurface.batchvertex3f_bufferoffset = 0;
8625 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8626 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8627 //                      rsurface.batchsvector3f_bufferoffset = 0;
8628 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8629 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8630 //                      rsurface.batchtvector3f_bufferoffset = 0;
8631 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8632 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8633 //                      rsurface.batchnormal3f_bufferoffset = 0;
8634                         // a single autosprite surface can contain multiple sprites...
8635                         for (j = 0;j < batchnumvertices - 3;j += 4)
8636                         {
8637                                 VectorClear(center);
8638                                 for (i = 0;i < 4;i++)
8639                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8640                                 VectorScale(center, 0.25f, center);
8641                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8642                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8643                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8644                                 for (i = 0;i < 4;i++)
8645                                 {
8646                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8647                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8648                                 }
8649                         }
8650                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8651                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8652                         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);
8653                         break;
8654                 case Q3DEFORM_AUTOSPRITE2:
8655                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8656                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8657                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8658                         VectorNormalize(newforward);
8659                         VectorNormalize(newright);
8660                         VectorNormalize(newup);
8661 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8662 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8663 //                      rsurface.batchvertex3f_bufferoffset = 0;
8664                         {
8665                                 const float *v1, *v2;
8666                                 vec3_t start, end;
8667                                 float f, l;
8668                                 struct
8669                                 {
8670                                         float length2;
8671                                         const float *v1;
8672                                         const float *v2;
8673                                 }
8674                                 shortest[2];
8675                                 memset(shortest, 0, sizeof(shortest));
8676                                 // a single autosprite surface can contain multiple sprites...
8677                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8678                                 {
8679                                         VectorClear(center);
8680                                         for (i = 0;i < 4;i++)
8681                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8682                                         VectorScale(center, 0.25f, center);
8683                                         // find the two shortest edges, then use them to define the
8684                                         // axis vectors for rotating around the central axis
8685                                         for (i = 0;i < 6;i++)
8686                                         {
8687                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8688                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8689                                                 l = VectorDistance2(v1, v2);
8690                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8691                                                 if (v1[2] != v2[2])
8692                                                         l += (1.0f / 1024.0f);
8693                                                 if (shortest[0].length2 > l || i == 0)
8694                                                 {
8695                                                         shortest[1] = shortest[0];
8696                                                         shortest[0].length2 = l;
8697                                                         shortest[0].v1 = v1;
8698                                                         shortest[0].v2 = v2;
8699                                                 }
8700                                                 else if (shortest[1].length2 > l || i == 1)
8701                                                 {
8702                                                         shortest[1].length2 = l;
8703                                                         shortest[1].v1 = v1;
8704                                                         shortest[1].v2 = v2;
8705                                                 }
8706                                         }
8707                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8708                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8709                                         // this calculates the right vector from the shortest edge
8710                                         // and the up vector from the edge midpoints
8711                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8712                                         VectorNormalize(right);
8713                                         VectorSubtract(end, start, up);
8714                                         VectorNormalize(up);
8715                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8716                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8717                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8718                                         VectorNegate(forward, forward);
8719                                         VectorReflect(forward, 0, up, forward);
8720                                         VectorNormalize(forward);
8721                                         CrossProduct(up, forward, newright);
8722                                         VectorNormalize(newright);
8723                                         // rotate the quad around the up axis vector, this is made
8724                                         // especially easy by the fact we know the quad is flat,
8725                                         // so we only have to subtract the center position and
8726                                         // measure distance along the right vector, and then
8727                                         // multiply that by the newright vector and add back the
8728                                         // center position
8729                                         // we also need to subtract the old position to undo the
8730                                         // displacement from the center, which we do with a
8731                                         // DotProduct, the subtraction/addition of center is also
8732                                         // optimized into DotProducts here
8733                                         l = DotProduct(right, center);
8734                                         for (i = 0;i < 4;i++)
8735                                         {
8736                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8737                                                 f = DotProduct(right, v1) - l;
8738                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8739                                         }
8740                                 }
8741                         }
8742                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8743                         {
8744 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8745 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8746 //                              rsurface.batchnormal3f_bufferoffset = 0;
8747                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8748                         }
8749                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8750                         {
8751 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8752 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8753 //                              rsurface.batchsvector3f_bufferoffset = 0;
8754 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8755 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8756 //                              rsurface.batchtvector3f_bufferoffset = 0;
8757                                 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);
8758                         }
8759                         break;
8760                 case Q3DEFORM_NORMAL:
8761                         // deform the normals to make reflections wavey
8762                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8763                         rsurface.batchnormal3f_vertexbuffer = NULL;
8764                         rsurface.batchnormal3f_bufferoffset = 0;
8765                         for (j = 0;j < batchnumvertices;j++)
8766                         {
8767                                 float vertex[3];
8768                                 float *normal = rsurface.batchnormal3f + 3*j;
8769                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8770                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8771                                 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]);
8772                                 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]);
8773                                 VectorNormalize(normal);
8774                         }
8775                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8776                         {
8777 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8778 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8779 //                              rsurface.batchsvector3f_bufferoffset = 0;
8780 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8781 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8782 //                              rsurface.batchtvector3f_bufferoffset = 0;
8783                                 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);
8784                         }
8785                         break;
8786                 case Q3DEFORM_WAVE:
8787                         // deform vertex array to make wavey water and flags and such
8788                         waveparms[0] = deform->waveparms[0];
8789                         waveparms[1] = deform->waveparms[1];
8790                         waveparms[2] = deform->waveparms[2];
8791                         waveparms[3] = deform->waveparms[3];
8792                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8793                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8794                         // this is how a divisor of vertex influence on deformation
8795                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8796                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8797 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8798 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8799 //                      rsurface.batchvertex3f_bufferoffset = 0;
8800 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8801 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8802 //                      rsurface.batchnormal3f_bufferoffset = 0;
8803                         for (j = 0;j < batchnumvertices;j++)
8804                         {
8805                                 // if the wavefunc depends on time, evaluate it per-vertex
8806                                 if (waveparms[3])
8807                                 {
8808                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8809                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8810                                 }
8811                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8812                         }
8813                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8814                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8815                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8816                         {
8817 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8818 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8819 //                              rsurface.batchsvector3f_bufferoffset = 0;
8820 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8821 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8822 //                              rsurface.batchtvector3f_bufferoffset = 0;
8823                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8824                         }
8825                         break;
8826                 case Q3DEFORM_BULGE:
8827                         // deform vertex array to make the surface have moving bulges
8828 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8829 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8830 //                      rsurface.batchvertex3f_bufferoffset = 0;
8831 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8832 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8833 //                      rsurface.batchnormal3f_bufferoffset = 0;
8834                         for (j = 0;j < batchnumvertices;j++)
8835                         {
8836                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8837                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8838                         }
8839                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8840                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8841                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8842                         {
8843 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8844 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8845 //                              rsurface.batchsvector3f_bufferoffset = 0;
8846 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8847 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8848 //                              rsurface.batchtvector3f_bufferoffset = 0;
8849                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8850                         }
8851                         break;
8852                 case Q3DEFORM_MOVE:
8853                         // deform vertex array
8854                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8855                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8856                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8857                         VectorScale(deform->parms, scale, waveparms);
8858 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8859 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8860 //                      rsurface.batchvertex3f_bufferoffset = 0;
8861                         for (j = 0;j < batchnumvertices;j++)
8862                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8863                         break;
8864                 }
8865         }
8866
8867         // generate texcoords based on the chosen texcoord source
8868         switch(rsurface.texture->tcgen.tcgen)
8869         {
8870         default:
8871         case Q3TCGEN_TEXTURE:
8872                 break;
8873         case Q3TCGEN_LIGHTMAP:
8874 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8875 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8876 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8877                 if (rsurface.batchtexcoordlightmap2f)
8878                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8879                 break;
8880         case Q3TCGEN_VECTOR:
8881 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8882 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8883 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8884                 for (j = 0;j < batchnumvertices;j++)
8885                 {
8886                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8887                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8888                 }
8889                 break;
8890         case Q3TCGEN_ENVIRONMENT:
8891                 // make environment reflections using a spheremap
8892                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8893                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8894                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8895                 for (j = 0;j < batchnumvertices;j++)
8896                 {
8897                         // identical to Q3A's method, but executed in worldspace so
8898                         // carried models can be shiny too
8899
8900                         float viewer[3], d, reflected[3], worldreflected[3];
8901
8902                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8903                         // VectorNormalize(viewer);
8904
8905                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8906
8907                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8908                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8909                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8910                         // note: this is proportinal to viewer, so we can normalize later
8911
8912                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8913                         VectorNormalize(worldreflected);
8914
8915                         // note: this sphere map only uses world x and z!
8916                         // so positive and negative y will LOOK THE SAME.
8917                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8918                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8919                 }
8920                 break;
8921         }
8922         // the only tcmod that needs software vertex processing is turbulent, so
8923         // check for it here and apply the changes if needed
8924         // and we only support that as the first one
8925         // (handling a mixture of turbulent and other tcmods would be problematic
8926         //  without punting it entirely to a software path)
8927         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8928         {
8929                 amplitude = rsurface.texture->tcmods[0].parms[1];
8930                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8931 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8932 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8933 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8934                 for (j = 0;j < batchnumvertices;j++)
8935                 {
8936                         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);
8937                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8938                 }
8939         }
8940
8941         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8942         {
8943                 // convert the modified arrays to vertex structs
8944 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8945 //              rsurface.batchvertexmeshbuffer = NULL;
8946                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8947                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8948                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8949                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8950                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8951                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8952                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8953                 {
8954                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8955                         {
8956                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8957                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8958                         }
8959                 }
8960                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8961                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8962                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8963                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8964                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8965                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8966                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8967                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8968                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8969         }
8970 }
8971
8972 void RSurf_DrawBatch(void)
8973 {
8974         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8975         // through the pipeline, killing it earlier in the pipeline would have
8976         // per-surface overhead rather than per-batch overhead, so it's best to
8977         // reject it here, before it hits glDraw.
8978         if (rsurface.batchnumtriangles == 0)
8979                 return;
8980 #if 0
8981         // batch debugging code
8982         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8983         {
8984                 int i;
8985                 int j;
8986                 int c;
8987                 const int *e;
8988                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8989                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8990                 {
8991                         c = e[i];
8992                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8993                         {
8994                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8995                                 {
8996                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8997                                                 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);
8998                                         break;
8999                                 }
9000                         }
9001                 }
9002         }
9003 #endif
9004         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);
9005 }
9006
9007 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9008 {
9009         // pick the closest matching water plane
9010         int planeindex, vertexindex, bestplaneindex = -1;
9011         float d, bestd;
9012         vec3_t vert;
9013         const float *v;
9014         r_waterstate_waterplane_t *p;
9015         qboolean prepared = false;
9016         bestd = 0;
9017         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9018         {
9019                 if(p->camera_entity != rsurface.texture->camera_entity)
9020                         continue;
9021                 d = 0;
9022                 if(!prepared)
9023                 {
9024                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9025                         prepared = true;
9026                         if(rsurface.batchnumvertices == 0)
9027                                 break;
9028                 }
9029                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9030                 {
9031                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9032                         d += fabs(PlaneDiff(vert, &p->plane));
9033                 }
9034                 if (bestd > d || bestplaneindex < 0)
9035                 {
9036                         bestd = d;
9037                         bestplaneindex = planeindex;
9038                 }
9039         }
9040         return bestplaneindex;
9041         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9042         // this situation though, as it might be better to render single larger
9043         // batches with useless stuff (backface culled for example) than to
9044         // render multiple smaller batches
9045 }
9046
9047 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9048 {
9049         int i;
9050         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9051         rsurface.passcolor4f_vertexbuffer = 0;
9052         rsurface.passcolor4f_bufferoffset = 0;
9053         for (i = 0;i < rsurface.batchnumvertices;i++)
9054                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9055 }
9056
9057 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9058 {
9059         int i;
9060         float f;
9061         const float *v;
9062         const float *c;
9063         float *c2;
9064         if (rsurface.passcolor4f)
9065         {
9066                 // generate color arrays
9067                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9068                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9069                 rsurface.passcolor4f_vertexbuffer = 0;
9070                 rsurface.passcolor4f_bufferoffset = 0;
9071                 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)
9072                 {
9073                         f = RSurf_FogVertex(v);
9074                         c2[0] = c[0] * f;
9075                         c2[1] = c[1] * f;
9076                         c2[2] = c[2] * f;
9077                         c2[3] = c[3];
9078                 }
9079         }
9080         else
9081         {
9082                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9083                 rsurface.passcolor4f_vertexbuffer = 0;
9084                 rsurface.passcolor4f_bufferoffset = 0;
9085                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9086                 {
9087                         f = RSurf_FogVertex(v);
9088                         c2[0] = f;
9089                         c2[1] = f;
9090                         c2[2] = f;
9091                         c2[3] = 1;
9092                 }
9093         }
9094 }
9095
9096 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9097 {
9098         int i;
9099         float f;
9100         const float *v;
9101         const float *c;
9102         float *c2;
9103         if (!rsurface.passcolor4f)
9104                 return;
9105         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9106         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9107         rsurface.passcolor4f_vertexbuffer = 0;
9108         rsurface.passcolor4f_bufferoffset = 0;
9109         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)
9110         {
9111                 f = RSurf_FogVertex(v);
9112                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9113                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9114                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9115                 c2[3] = c[3];
9116         }
9117 }
9118
9119 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9120 {
9121         int i;
9122         const float *c;
9123         float *c2;
9124         if (!rsurface.passcolor4f)
9125                 return;
9126         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9127         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9128         rsurface.passcolor4f_vertexbuffer = 0;
9129         rsurface.passcolor4f_bufferoffset = 0;
9130         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9131         {
9132                 c2[0] = c[0] * r;
9133                 c2[1] = c[1] * g;
9134                 c2[2] = c[2] * b;
9135                 c2[3] = c[3] * a;
9136         }
9137 }
9138
9139 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9140 {
9141         int i;
9142         const float *c;
9143         float *c2;
9144         if (!rsurface.passcolor4f)
9145                 return;
9146         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9147         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9148         rsurface.passcolor4f_vertexbuffer = 0;
9149         rsurface.passcolor4f_bufferoffset = 0;
9150         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9151         {
9152                 c2[0] = c[0] + r_refdef.scene.ambient;
9153                 c2[1] = c[1] + r_refdef.scene.ambient;
9154                 c2[2] = c[2] + r_refdef.scene.ambient;
9155                 c2[3] = c[3];
9156         }
9157 }
9158
9159 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9160 {
9161         // TODO: optimize
9162         rsurface.passcolor4f = NULL;
9163         rsurface.passcolor4f_vertexbuffer = 0;
9164         rsurface.passcolor4f_bufferoffset = 0;
9165         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9166         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9167         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9168         GL_Color(r, g, b, a);
9169         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9170         RSurf_DrawBatch();
9171 }
9172
9173 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9174 {
9175         // TODO: optimize applyfog && applycolor case
9176         // just apply fog if necessary, and tint the fog color array if necessary
9177         rsurface.passcolor4f = NULL;
9178         rsurface.passcolor4f_vertexbuffer = 0;
9179         rsurface.passcolor4f_bufferoffset = 0;
9180         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9181         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9182         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9183         GL_Color(r, g, b, a);
9184         RSurf_DrawBatch();
9185 }
9186
9187 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9188 {
9189         // TODO: optimize
9190         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9191         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9192         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9193         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9194         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9195         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9196         GL_Color(r, g, b, a);
9197         RSurf_DrawBatch();
9198 }
9199
9200 static void RSurf_DrawBatch_GL11_ClampColor(void)
9201 {
9202         int i;
9203         const float *c1;
9204         float *c2;
9205         if (!rsurface.passcolor4f)
9206                 return;
9207         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9208         {
9209                 c2[0] = bound(0.0f, c1[0], 1.0f);
9210                 c2[1] = bound(0.0f, c1[1], 1.0f);
9211                 c2[2] = bound(0.0f, c1[2], 1.0f);
9212                 c2[3] = bound(0.0f, c1[3], 1.0f);
9213         }
9214 }
9215
9216 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9217 {
9218         int i;
9219         float f;
9220         const float *v;
9221         const float *n;
9222         float *c;
9223         //vec3_t eyedir;
9224
9225         // fake shading
9226         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9227         rsurface.passcolor4f_vertexbuffer = 0;
9228         rsurface.passcolor4f_bufferoffset = 0;
9229         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)
9230         {
9231                 f = -DotProduct(r_refdef.view.forward, n);
9232                 f = max(0, f);
9233                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9234                 f *= r_refdef.lightmapintensity;
9235                 Vector4Set(c, f, f, f, 1);
9236         }
9237 }
9238
9239 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9240 {
9241         RSurf_DrawBatch_GL11_ApplyFakeLight();
9242         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9243         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9244         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9245         GL_Color(r, g, b, a);
9246         RSurf_DrawBatch();
9247 }
9248
9249 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9250 {
9251         int i;
9252         float f;
9253         float alpha;
9254         const float *v;
9255         const float *n;
9256         float *c;
9257         vec3_t ambientcolor;
9258         vec3_t diffusecolor;
9259         vec3_t lightdir;
9260         // TODO: optimize
9261         // model lighting
9262         VectorCopy(rsurface.modellight_lightdir, lightdir);
9263         f = 0.5f * r_refdef.lightmapintensity;
9264         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9265         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9266         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9267         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9268         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9269         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9270         alpha = *a;
9271         if (VectorLength2(diffusecolor) > 0)
9272         {
9273                 // q3-style directional shading
9274                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9275                 rsurface.passcolor4f_vertexbuffer = 0;
9276                 rsurface.passcolor4f_bufferoffset = 0;
9277                 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)
9278                 {
9279                         if ((f = DotProduct(n, lightdir)) > 0)
9280                                 VectorMA(ambientcolor, f, diffusecolor, c);
9281                         else
9282                                 VectorCopy(ambientcolor, c);
9283                         c[3] = alpha;
9284                 }
9285                 *r = 1;
9286                 *g = 1;
9287                 *b = 1;
9288                 *a = 1;
9289                 *applycolor = false;
9290         }
9291         else
9292         {
9293                 *r = ambientcolor[0];
9294                 *g = ambientcolor[1];
9295                 *b = ambientcolor[2];
9296                 rsurface.passcolor4f = NULL;
9297                 rsurface.passcolor4f_vertexbuffer = 0;
9298                 rsurface.passcolor4f_bufferoffset = 0;
9299         }
9300 }
9301
9302 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9303 {
9304         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9305         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9306         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9307         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9308         GL_Color(r, g, b, a);
9309         RSurf_DrawBatch();
9310 }
9311
9312 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9313 {
9314         int i;
9315         float f;
9316         const float *v;
9317         float *c;
9318
9319         // fake shading
9320         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9321         rsurface.passcolor4f_vertexbuffer = 0;
9322         rsurface.passcolor4f_bufferoffset = 0;
9323
9324         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9325         {
9326                 f = 1 - RSurf_FogVertex(v);
9327                 c[0] = r;
9328                 c[1] = g;
9329                 c[2] = b;
9330                 c[3] = f * a;
9331         }
9332 }
9333
9334 void RSurf_SetupDepthAndCulling(void)
9335 {
9336         // submodels are biased to avoid z-fighting with world surfaces that they
9337         // may be exactly overlapping (avoids z-fighting artifacts on certain
9338         // doors and things in Quake maps)
9339         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9340         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9341         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9342         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9343 }
9344
9345 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9346 {
9347         // transparent sky would be ridiculous
9348         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9349                 return;
9350         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9351         skyrenderlater = true;
9352         RSurf_SetupDepthAndCulling();
9353         GL_DepthMask(true);
9354         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9355         // skymasking on them, and Quake3 never did sky masking (unlike
9356         // software Quake and software Quake2), so disable the sky masking
9357         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9358         // and skymasking also looks very bad when noclipping outside the
9359         // level, so don't use it then either.
9360         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9361         {
9362                 R_Mesh_ResetTextureState();
9363                 if (skyrendermasked)
9364                 {
9365                         R_SetupShader_DepthOrShadow();
9366                         // depth-only (masking)
9367                         GL_ColorMask(0,0,0,0);
9368                         // just to make sure that braindead drivers don't draw
9369                         // anything despite that colormask...
9370                         GL_BlendFunc(GL_ZERO, GL_ONE);
9371                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9372                         if (rsurface.batchvertex3fbuffer)
9373                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9374                         else
9375                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9376                 }
9377                 else
9378                 {
9379                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9380                         // fog sky
9381                         GL_BlendFunc(GL_ONE, GL_ZERO);
9382                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9383                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9384                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9385                 }
9386                 RSurf_DrawBatch();
9387                 if (skyrendermasked)
9388                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9389         }
9390         R_Mesh_ResetTextureState();
9391         GL_Color(1, 1, 1, 1);
9392 }
9393
9394 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9395 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9396 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9397 {
9398         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9399                 return;
9400         if (prepass)
9401         {
9402                 // render screenspace normalmap to texture
9403                 GL_DepthMask(true);
9404                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9405                 RSurf_DrawBatch();
9406                 return;
9407         }
9408
9409         // bind lightmap texture
9410
9411         // water/refraction/reflection/camera surfaces have to be handled specially
9412         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9413         {
9414                 int start, end, startplaneindex;
9415                 for (start = 0;start < texturenumsurfaces;start = end)
9416                 {
9417                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9418                         if(startplaneindex < 0)
9419                         {
9420                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9421                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9422                                 end = start + 1;
9423                                 continue;
9424                         }
9425                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9426                                 ;
9427                         // now that we have a batch using the same planeindex, render it
9428                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9429                         {
9430                                 // render water or distortion background
9431                                 GL_DepthMask(true);
9432                                 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));
9433                                 RSurf_DrawBatch();
9434                                 // blend surface on top
9435                                 GL_DepthMask(false);
9436                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9437                                 RSurf_DrawBatch();
9438                         }
9439                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9440                         {
9441                                 // render surface with reflection texture as input
9442                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9443                                 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));
9444                                 RSurf_DrawBatch();
9445                         }
9446                 }
9447                 return;
9448         }
9449
9450         // render surface batch normally
9451         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9452         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9453         RSurf_DrawBatch();
9454 }
9455
9456 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9457 {
9458         // OpenGL 1.3 path - anything not completely ancient
9459         qboolean applycolor;
9460         qboolean applyfog;
9461         int layerindex;
9462         const texturelayer_t *layer;
9463         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);
9464         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9465
9466         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9467         {
9468                 vec4_t layercolor;
9469                 int layertexrgbscale;
9470                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9471                 {
9472                         if (layerindex == 0)
9473                                 GL_AlphaTest(true);
9474                         else
9475                         {
9476                                 GL_AlphaTest(false);
9477                                 GL_DepthFunc(GL_EQUAL);
9478                         }
9479                 }
9480                 GL_DepthMask(layer->depthmask && writedepth);
9481                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9482                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9483                 {
9484                         layertexrgbscale = 4;
9485                         VectorScale(layer->color, 0.25f, layercolor);
9486                 }
9487                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9488                 {
9489                         layertexrgbscale = 2;
9490                         VectorScale(layer->color, 0.5f, layercolor);
9491                 }
9492                 else
9493                 {
9494                         layertexrgbscale = 1;
9495                         VectorScale(layer->color, 1.0f, layercolor);
9496                 }
9497                 layercolor[3] = layer->color[3];
9498                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9499                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9500                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9501                 switch (layer->type)
9502                 {
9503                 case TEXTURELAYERTYPE_LITTEXTURE:
9504                         // single-pass lightmapped texture with 2x rgbscale
9505                         R_Mesh_TexBind(0, r_texture_white);
9506                         R_Mesh_TexMatrix(0, NULL);
9507                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9508                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9509                         R_Mesh_TexBind(1, layer->texture);
9510                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9511                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9512                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9513                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9514                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9515                         else if (FAKELIGHT_ENABLED)
9516                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9517                         else if (rsurface.uselightmaptexture)
9518                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9519                         else
9520                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9521                         break;
9522                 case TEXTURELAYERTYPE_TEXTURE:
9523                         // singletexture unlit texture with transparency support
9524                         R_Mesh_TexBind(0, layer->texture);
9525                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9526                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9527                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9528                         R_Mesh_TexBind(1, 0);
9529                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9530                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9531                         break;
9532                 case TEXTURELAYERTYPE_FOG:
9533                         // singletexture fogging
9534                         if (layer->texture)
9535                         {
9536                                 R_Mesh_TexBind(0, layer->texture);
9537                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9538                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9539                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9540                         }
9541                         else
9542                         {
9543                                 R_Mesh_TexBind(0, 0);
9544                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9545                         }
9546                         R_Mesh_TexBind(1, 0);
9547                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9548                         // generate a color array for the fog pass
9549                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9550                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9551                         RSurf_DrawBatch();
9552                         break;
9553                 default:
9554                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9555                 }
9556         }
9557         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9558         {
9559                 GL_DepthFunc(GL_LEQUAL);
9560                 GL_AlphaTest(false);
9561         }
9562 }
9563
9564 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9565 {
9566         // OpenGL 1.1 - crusty old voodoo path
9567         qboolean applyfog;
9568         int layerindex;
9569         const texturelayer_t *layer;
9570         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);
9571         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9572
9573         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9574         {
9575                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9576                 {
9577                         if (layerindex == 0)
9578                                 GL_AlphaTest(true);
9579                         else
9580                         {
9581                                 GL_AlphaTest(false);
9582                                 GL_DepthFunc(GL_EQUAL);
9583                         }
9584                 }
9585                 GL_DepthMask(layer->depthmask && writedepth);
9586                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9587                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9588                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9589                 switch (layer->type)
9590                 {
9591                 case TEXTURELAYERTYPE_LITTEXTURE:
9592                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9593                         {
9594                                 // two-pass lit texture with 2x rgbscale
9595                                 // first the lightmap pass
9596                                 R_Mesh_TexBind(0, r_texture_white);
9597                                 R_Mesh_TexMatrix(0, NULL);
9598                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9599                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9600                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9601                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9602                                 else if (FAKELIGHT_ENABLED)
9603                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9604                                 else if (rsurface.uselightmaptexture)
9605                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9606                                 else
9607                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9608                                 // then apply the texture to it
9609                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9610                                 R_Mesh_TexBind(0, layer->texture);
9611                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9612                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9613                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9614                                 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);
9615                         }
9616                         else
9617                         {
9618                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9619                                 R_Mesh_TexBind(0, layer->texture);
9620                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9621                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9622                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9623                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9624                                         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);
9625                                 else
9626                                         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);
9627                         }
9628                         break;
9629                 case TEXTURELAYERTYPE_TEXTURE:
9630                         // singletexture unlit texture with transparency support
9631                         R_Mesh_TexBind(0, layer->texture);
9632                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9633                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9634                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9635                         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);
9636                         break;
9637                 case TEXTURELAYERTYPE_FOG:
9638                         // singletexture fogging
9639                         if (layer->texture)
9640                         {
9641                                 R_Mesh_TexBind(0, layer->texture);
9642                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9643                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9644                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9645                         }
9646                         else
9647                         {
9648                                 R_Mesh_TexBind(0, 0);
9649                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9650                         }
9651                         // generate a color array for the fog pass
9652                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9653                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9654                         RSurf_DrawBatch();
9655                         break;
9656                 default:
9657                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9658                 }
9659         }
9660         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9661         {
9662                 GL_DepthFunc(GL_LEQUAL);
9663                 GL_AlphaTest(false);
9664         }
9665 }
9666
9667 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9668 {
9669         int vi;
9670         int j;
9671         r_vertexgeneric_t *batchvertex;
9672         float c[4];
9673
9674 //      R_Mesh_ResetTextureState();
9675         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9676
9677         if(rsurface.texture && rsurface.texture->currentskinframe)
9678         {
9679                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9680                 c[3] *= rsurface.texture->currentalpha;
9681         }
9682         else
9683         {
9684                 c[0] = 1;
9685                 c[1] = 0;
9686                 c[2] = 1;
9687                 c[3] = 1;
9688         }
9689
9690         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9691         {
9692                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9693                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9694                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9695         }
9696
9697         // brighten it up (as texture value 127 means "unlit")
9698         c[0] *= 2 * r_refdef.view.colorscale;
9699         c[1] *= 2 * r_refdef.view.colorscale;
9700         c[2] *= 2 * r_refdef.view.colorscale;
9701
9702         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9703                 c[3] *= r_wateralpha.value;
9704
9705         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9706         {
9707                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9708                 GL_DepthMask(false);
9709         }
9710         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9711         {
9712                 GL_BlendFunc(GL_ONE, GL_ONE);
9713                 GL_DepthMask(false);
9714         }
9715         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9716         {
9717                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9718                 GL_DepthMask(false);
9719         }
9720         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9721         {
9722                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9723                 GL_DepthMask(false);
9724         }
9725         else
9726         {
9727                 GL_BlendFunc(GL_ONE, GL_ZERO);
9728                 GL_DepthMask(writedepth);
9729         }
9730
9731         if (r_showsurfaces.integer == 3)
9732         {
9733                 rsurface.passcolor4f = NULL;
9734
9735                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9736                 {
9737                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9738
9739                         rsurface.passcolor4f = NULL;
9740                         rsurface.passcolor4f_vertexbuffer = 0;
9741                         rsurface.passcolor4f_bufferoffset = 0;
9742                 }
9743                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9744                 {
9745                         qboolean applycolor = true;
9746                         float one = 1.0;
9747
9748                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9749
9750                         r_refdef.lightmapintensity = 1;
9751                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9752                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9753                 }
9754                 else if (FAKELIGHT_ENABLED)
9755                 {
9756                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9757
9758                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9759                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9760                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9761                 }
9762                 else
9763                 {
9764                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9765
9766                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9767                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9768                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9769                 }
9770
9771                 if(!rsurface.passcolor4f)
9772                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9773
9774                 RSurf_DrawBatch_GL11_ApplyAmbient();
9775                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9776                 if(r_refdef.fogenabled)
9777                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9778                 RSurf_DrawBatch_GL11_ClampColor();
9779
9780                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9781                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9782                 RSurf_DrawBatch();
9783         }
9784         else if (!r_refdef.view.showdebug)
9785         {
9786                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9787                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9788                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9789                 {
9790                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9791                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9792                 }
9793                 R_Mesh_PrepareVertices_Generic_Unlock();
9794                 RSurf_DrawBatch();
9795         }
9796         else if (r_showsurfaces.integer == 4)
9797         {
9798                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9799                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9800                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9801                 {
9802                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9803                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9804                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9805                 }
9806                 R_Mesh_PrepareVertices_Generic_Unlock();
9807                 RSurf_DrawBatch();
9808         }
9809         else if (r_showsurfaces.integer == 2)
9810         {
9811                 const int *e;
9812                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9813                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9814                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9815                 {
9816                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9817                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9818                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9819                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9820                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9821                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9822                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9823                 }
9824                 R_Mesh_PrepareVertices_Generic_Unlock();
9825                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9826         }
9827         else
9828         {
9829                 int texturesurfaceindex;
9830                 int k;
9831                 const msurface_t *surface;
9832                 float surfacecolor4f[4];
9833                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9834                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9835                 vi = 0;
9836                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9837                 {
9838                         surface = texturesurfacelist[texturesurfaceindex];
9839                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9840                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9841                         for (j = 0;j < surface->num_vertices;j++)
9842                         {
9843                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9844                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9845                                 vi++;
9846                         }
9847                 }
9848                 R_Mesh_PrepareVertices_Generic_Unlock();
9849                 RSurf_DrawBatch();
9850         }
9851 }
9852
9853 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9854 {
9855         CHECKGLERROR
9856         RSurf_SetupDepthAndCulling();
9857         if (r_showsurfaces.integer)
9858         {
9859                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9860                 return;
9861         }
9862         switch (vid.renderpath)
9863         {
9864         case RENDERPATH_GL20:
9865         case RENDERPATH_D3D9:
9866         case RENDERPATH_D3D10:
9867         case RENDERPATH_D3D11:
9868         case RENDERPATH_SOFT:
9869         case RENDERPATH_GLES2:
9870                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9871                 break;
9872         case RENDERPATH_GL13:
9873                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9874                 break;
9875         case RENDERPATH_GL11:
9876                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9877                 break;
9878         }
9879         CHECKGLERROR
9880 }
9881
9882 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9883 {
9884         CHECKGLERROR
9885         RSurf_SetupDepthAndCulling();
9886         if (r_showsurfaces.integer)
9887         {
9888                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9889                 return;
9890         }
9891         switch (vid.renderpath)
9892         {
9893         case RENDERPATH_GL20:
9894         case RENDERPATH_D3D9:
9895         case RENDERPATH_D3D10:
9896         case RENDERPATH_D3D11:
9897         case RENDERPATH_SOFT:
9898         case RENDERPATH_GLES2:
9899                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9900                 break;
9901         case RENDERPATH_GL13:
9902                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9903                 break;
9904         case RENDERPATH_GL11:
9905                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9906                 break;
9907         }
9908         CHECKGLERROR
9909 }
9910
9911 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9912 {
9913         int i, j;
9914         int texturenumsurfaces, endsurface;
9915         texture_t *texture;
9916         const msurface_t *surface;
9917 #define MAXBATCH_TRANSPARENTSURFACES 256
9918         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9919
9920         // if the model is static it doesn't matter what value we give for
9921         // wantnormals and wanttangents, so this logic uses only rules applicable
9922         // to a model, knowing that they are meaningless otherwise
9923         if (ent == r_refdef.scene.worldentity)
9924                 RSurf_ActiveWorldEntity();
9925         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9926                 RSurf_ActiveModelEntity(ent, false, false, false);
9927         else
9928         {
9929                 switch (vid.renderpath)
9930                 {
9931                 case RENDERPATH_GL20:
9932                 case RENDERPATH_D3D9:
9933                 case RENDERPATH_D3D10:
9934                 case RENDERPATH_D3D11:
9935                 case RENDERPATH_SOFT:
9936                 case RENDERPATH_GLES2:
9937                         RSurf_ActiveModelEntity(ent, true, true, false);
9938                         break;
9939                 case RENDERPATH_GL13:
9940                 case RENDERPATH_GL11:
9941                         RSurf_ActiveModelEntity(ent, true, false, false);
9942                         break;
9943                 }
9944         }
9945
9946         if (r_transparentdepthmasking.integer)
9947         {
9948                 qboolean setup = false;
9949                 for (i = 0;i < numsurfaces;i = j)
9950                 {
9951                         j = i + 1;
9952                         surface = rsurface.modelsurfaces + surfacelist[i];
9953                         texture = surface->texture;
9954                         rsurface.texture = R_GetCurrentTexture(texture);
9955                         rsurface.lightmaptexture = NULL;
9956                         rsurface.deluxemaptexture = NULL;
9957                         rsurface.uselightmaptexture = false;
9958                         // scan ahead until we find a different texture
9959                         endsurface = min(i + 1024, numsurfaces);
9960                         texturenumsurfaces = 0;
9961                         texturesurfacelist[texturenumsurfaces++] = surface;
9962                         for (;j < endsurface;j++)
9963                         {
9964                                 surface = rsurface.modelsurfaces + surfacelist[j];
9965                                 if (texture != surface->texture)
9966                                         break;
9967                                 texturesurfacelist[texturenumsurfaces++] = surface;
9968                         }
9969                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9970                                 continue;
9971                         // render the range of surfaces as depth
9972                         if (!setup)
9973                         {
9974                                 setup = true;
9975                                 GL_ColorMask(0,0,0,0);
9976                                 GL_Color(1,1,1,1);
9977                                 GL_DepthTest(true);
9978                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9979                                 GL_DepthMask(true);
9980 //                              R_Mesh_ResetTextureState();
9981                                 R_SetupShader_DepthOrShadow();
9982                         }
9983                         RSurf_SetupDepthAndCulling();
9984                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9985                         if (rsurface.batchvertex3fbuffer)
9986                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9987                         else
9988                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9989                         RSurf_DrawBatch();
9990                 }
9991                 if (setup)
9992                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9993         }
9994
9995         for (i = 0;i < numsurfaces;i = j)
9996         {
9997                 j = i + 1;
9998                 surface = rsurface.modelsurfaces + surfacelist[i];
9999                 texture = surface->texture;
10000                 rsurface.texture = R_GetCurrentTexture(texture);
10001                 // scan ahead until we find a different texture
10002                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10003                 texturenumsurfaces = 0;
10004                 texturesurfacelist[texturenumsurfaces++] = surface;
10005                 if(FAKELIGHT_ENABLED)
10006                 {
10007                         rsurface.lightmaptexture = NULL;
10008                         rsurface.deluxemaptexture = NULL;
10009                         rsurface.uselightmaptexture = false;
10010                         for (;j < endsurface;j++)
10011                         {
10012                                 surface = rsurface.modelsurfaces + surfacelist[j];
10013                                 if (texture != surface->texture)
10014                                         break;
10015                                 texturesurfacelist[texturenumsurfaces++] = surface;
10016                         }
10017                 }
10018                 else
10019                 {
10020                         rsurface.lightmaptexture = surface->lightmaptexture;
10021                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10022                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10023                         for (;j < endsurface;j++)
10024                         {
10025                                 surface = rsurface.modelsurfaces + surfacelist[j];
10026                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10027                                         break;
10028                                 texturesurfacelist[texturenumsurfaces++] = surface;
10029                         }
10030                 }
10031                 // render the range of surfaces
10032                 if (ent == r_refdef.scene.worldentity)
10033                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10034                 else
10035                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10036         }
10037         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10038 }
10039
10040 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10041 {
10042         // transparent surfaces get pushed off into the transparent queue
10043         int surfacelistindex;
10044         const msurface_t *surface;
10045         vec3_t tempcenter, center;
10046         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10047         {
10048                 surface = texturesurfacelist[surfacelistindex];
10049                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10050                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10051                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10052                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10053                 if (queueentity->transparent_offset) // transparent offset
10054                 {
10055                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10056                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10057                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10058                 }
10059                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10060         }
10061 }
10062
10063 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10064 {
10065         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10066                 return;
10067         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10068                 return;
10069         RSurf_SetupDepthAndCulling();
10070         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10071         if (rsurface.batchvertex3fbuffer)
10072                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10073         else
10074                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10075         RSurf_DrawBatch();
10076 }
10077
10078 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10079 {
10080         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10081         CHECKGLERROR
10082         if (depthonly)
10083                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10084         else if (prepass)
10085         {
10086                 if (!rsurface.texture->currentnumlayers)
10087                         return;
10088                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10089                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10090                 else
10091                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10092         }
10093         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10094                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10095         else if (!rsurface.texture->currentnumlayers)
10096                 return;
10097         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10098         {
10099                 // in the deferred case, transparent surfaces were queued during prepass
10100                 if (!r_shadow_usingdeferredprepass)
10101                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10102         }
10103         else
10104         {
10105                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10106                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10107         }
10108         CHECKGLERROR
10109 }
10110
10111 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10112 {
10113         int i, j;
10114         texture_t *texture;
10115         R_FrameData_SetMark();
10116         // break the surface list down into batches by texture and use of lightmapping
10117         for (i = 0;i < numsurfaces;i = j)
10118         {
10119                 j = i + 1;
10120                 // texture is the base texture pointer, rsurface.texture is the
10121                 // current frame/skin the texture is directing us to use (for example
10122                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10123                 // use skin 1 instead)
10124                 texture = surfacelist[i]->texture;
10125                 rsurface.texture = R_GetCurrentTexture(texture);
10126                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10127                 {
10128                         // if this texture is not the kind we want, skip ahead to the next one
10129                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10130                                 ;
10131                         continue;
10132                 }
10133                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10134                 {
10135                         rsurface.lightmaptexture = NULL;
10136                         rsurface.deluxemaptexture = NULL;
10137                         rsurface.uselightmaptexture = false;
10138                         // simply scan ahead until we find a different texture or lightmap state
10139                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10140                                 ;
10141                 }
10142                 else
10143                 {
10144                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10145                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10146                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10147                         // simply scan ahead until we find a different texture or lightmap state
10148                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10149                                 ;
10150                 }
10151                 // render the range of surfaces
10152                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10153         }
10154         R_FrameData_ReturnToMark();
10155 }
10156
10157 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10158 {
10159         CHECKGLERROR
10160         if (depthonly)
10161                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10162         else if (prepass)
10163         {
10164                 if (!rsurface.texture->currentnumlayers)
10165                         return;
10166                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10167                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10168                 else
10169                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10170         }
10171         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10172                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10173         else if (!rsurface.texture->currentnumlayers)
10174                 return;
10175         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10176         {
10177                 // in the deferred case, transparent surfaces were queued during prepass
10178                 if (!r_shadow_usingdeferredprepass)
10179                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10180         }
10181         else
10182         {
10183                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10184                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10185         }
10186         CHECKGLERROR
10187 }
10188
10189 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10190 {
10191         int i, j;
10192         texture_t *texture;
10193         R_FrameData_SetMark();
10194         // break the surface list down into batches by texture and use of lightmapping
10195         for (i = 0;i < numsurfaces;i = j)
10196         {
10197                 j = i + 1;
10198                 // texture is the base texture pointer, rsurface.texture is the
10199                 // current frame/skin the texture is directing us to use (for example
10200                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10201                 // use skin 1 instead)
10202                 texture = surfacelist[i]->texture;
10203                 rsurface.texture = R_GetCurrentTexture(texture);
10204                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10205                 {
10206                         // if this texture is not the kind we want, skip ahead to the next one
10207                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10208                                 ;
10209                         continue;
10210                 }
10211                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10212                 {
10213                         rsurface.lightmaptexture = NULL;
10214                         rsurface.deluxemaptexture = NULL;
10215                         rsurface.uselightmaptexture = false;
10216                         // simply scan ahead until we find a different texture or lightmap state
10217                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10218                                 ;
10219                 }
10220                 else
10221                 {
10222                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10223                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10224                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10225                         // simply scan ahead until we find a different texture or lightmap state
10226                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10227                                 ;
10228                 }
10229                 // render the range of surfaces
10230                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10231         }
10232         R_FrameData_ReturnToMark();
10233 }
10234
10235 float locboxvertex3f[6*4*3] =
10236 {
10237         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10238         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10239         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10240         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10241         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10242         1,0,0, 0,0,0, 0,1,0, 1,1,0
10243 };
10244
10245 unsigned short locboxelements[6*2*3] =
10246 {
10247          0, 1, 2, 0, 2, 3,
10248          4, 5, 6, 4, 6, 7,
10249          8, 9,10, 8,10,11,
10250         12,13,14, 12,14,15,
10251         16,17,18, 16,18,19,
10252         20,21,22, 20,22,23
10253 };
10254
10255 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10256 {
10257         int i, j;
10258         cl_locnode_t *loc = (cl_locnode_t *)ent;
10259         vec3_t mins, size;
10260         float vertex3f[6*4*3];
10261         CHECKGLERROR
10262         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10263         GL_DepthMask(false);
10264         GL_DepthRange(0, 1);
10265         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10266         GL_DepthTest(true);
10267         GL_CullFace(GL_NONE);
10268         R_EntityMatrix(&identitymatrix);
10269
10270 //      R_Mesh_ResetTextureState();
10271
10272         i = surfacelist[0];
10273         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10274                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10275                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10276                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10277
10278         if (VectorCompare(loc->mins, loc->maxs))
10279         {
10280                 VectorSet(size, 2, 2, 2);
10281                 VectorMA(loc->mins, -0.5f, size, mins);
10282         }
10283         else
10284         {
10285                 VectorCopy(loc->mins, mins);
10286                 VectorSubtract(loc->maxs, loc->mins, size);
10287         }
10288
10289         for (i = 0;i < 6*4*3;)
10290                 for (j = 0;j < 3;j++, i++)
10291                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10292
10293         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10294         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10295         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10296 }
10297
10298 void R_DrawLocs(void)
10299 {
10300         int index;
10301         cl_locnode_t *loc, *nearestloc;
10302         vec3_t center;
10303         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10304         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10305         {
10306                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10307                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10308         }
10309 }
10310
10311 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10312 {
10313         if (decalsystem->decals)
10314                 Mem_Free(decalsystem->decals);
10315         memset(decalsystem, 0, sizeof(*decalsystem));
10316 }
10317
10318 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)
10319 {
10320         tridecal_t *decal;
10321         tridecal_t *decals;
10322         int i;
10323
10324         // expand or initialize the system
10325         if (decalsystem->maxdecals <= decalsystem->numdecals)
10326         {
10327                 decalsystem_t old = *decalsystem;
10328                 qboolean useshortelements;
10329                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10330                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10331                 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)));
10332                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10333                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10334                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10335                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10336                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10337                 if (decalsystem->numdecals)
10338                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10339                 if (old.decals)
10340                         Mem_Free(old.decals);
10341                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10342                         decalsystem->element3i[i] = i;
10343                 if (useshortelements)
10344                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10345                                 decalsystem->element3s[i] = i;
10346         }
10347
10348         // grab a decal and search for another free slot for the next one
10349         decals = decalsystem->decals;
10350         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10351         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10352                 ;
10353         decalsystem->freedecal = i;
10354         if (decalsystem->numdecals <= i)
10355                 decalsystem->numdecals = i + 1;
10356
10357         // initialize the decal
10358         decal->lived = 0;
10359         decal->triangleindex = triangleindex;
10360         decal->surfaceindex = surfaceindex;
10361         decal->decalsequence = decalsequence;
10362         decal->color4f[0][0] = c0[0];
10363         decal->color4f[0][1] = c0[1];
10364         decal->color4f[0][2] = c0[2];
10365         decal->color4f[0][3] = 1;
10366         decal->color4f[1][0] = c1[0];
10367         decal->color4f[1][1] = c1[1];
10368         decal->color4f[1][2] = c1[2];
10369         decal->color4f[1][3] = 1;
10370         decal->color4f[2][0] = c2[0];
10371         decal->color4f[2][1] = c2[1];
10372         decal->color4f[2][2] = c2[2];
10373         decal->color4f[2][3] = 1;
10374         decal->vertex3f[0][0] = v0[0];
10375         decal->vertex3f[0][1] = v0[1];
10376         decal->vertex3f[0][2] = v0[2];
10377         decal->vertex3f[1][0] = v1[0];
10378         decal->vertex3f[1][1] = v1[1];
10379         decal->vertex3f[1][2] = v1[2];
10380         decal->vertex3f[2][0] = v2[0];
10381         decal->vertex3f[2][1] = v2[1];
10382         decal->vertex3f[2][2] = v2[2];
10383         decal->texcoord2f[0][0] = t0[0];
10384         decal->texcoord2f[0][1] = t0[1];
10385         decal->texcoord2f[1][0] = t1[0];
10386         decal->texcoord2f[1][1] = t1[1];
10387         decal->texcoord2f[2][0] = t2[0];
10388         decal->texcoord2f[2][1] = t2[1];
10389         TriangleNormal(v0, v1, v2, decal->plane);
10390         VectorNormalize(decal->plane);
10391         decal->plane[3] = DotProduct(v0, decal->plane);
10392 }
10393
10394 extern cvar_t cl_decals_bias;
10395 extern cvar_t cl_decals_models;
10396 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10397 // baseparms, parms, temps
10398 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)
10399 {
10400         int cornerindex;
10401         int index;
10402         float v[9][3];
10403         const float *vertex3f;
10404         const float *normal3f;
10405         int numpoints;
10406         float points[2][9][3];
10407         float temp[3];
10408         float tc[9][2];
10409         float f;
10410         float c[9][4];
10411         const int *e;
10412
10413         e = rsurface.modelelement3i + 3*triangleindex;
10414
10415         vertex3f = rsurface.modelvertex3f;
10416         normal3f = rsurface.modelnormal3f;
10417
10418         if (normal3f)
10419         {
10420                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10421                 {
10422                         index = 3*e[cornerindex];
10423                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10424                 }
10425         }
10426         else
10427         {
10428                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10429                 {
10430                         index = 3*e[cornerindex];
10431                         VectorCopy(vertex3f + index, v[cornerindex]);
10432                 }
10433         }
10434
10435         // cull backfaces
10436         //TriangleNormal(v[0], v[1], v[2], normal);
10437         //if (DotProduct(normal, localnormal) < 0.0f)
10438         //      continue;
10439         // clip by each of the box planes formed from the projection matrix
10440         // if anything survives, we emit the decal
10441         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]);
10442         if (numpoints < 3)
10443                 return;
10444         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]);
10445         if (numpoints < 3)
10446                 return;
10447         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]);
10448         if (numpoints < 3)
10449                 return;
10450         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]);
10451         if (numpoints < 3)
10452                 return;
10453         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]);
10454         if (numpoints < 3)
10455                 return;
10456         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]);
10457         if (numpoints < 3)
10458                 return;
10459         // some part of the triangle survived, so we have to accept it...
10460         if (dynamic)
10461         {
10462                 // dynamic always uses the original triangle
10463                 numpoints = 3;
10464                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10465                 {
10466                         index = 3*e[cornerindex];
10467                         VectorCopy(vertex3f + index, v[cornerindex]);
10468                 }
10469         }
10470         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10471         {
10472                 // convert vertex positions to texcoords
10473                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10474                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10475                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10476                 // calculate distance fade from the projection origin
10477                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10478                 f = bound(0.0f, f, 1.0f);
10479                 c[cornerindex][0] = r * f;
10480                 c[cornerindex][1] = g * f;
10481                 c[cornerindex][2] = b * f;
10482                 c[cornerindex][3] = 1.0f;
10483                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10484         }
10485         if (dynamic)
10486                 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);
10487         else
10488                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10489                         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);
10490 }
10491 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)
10492 {
10493         matrix4x4_t projection;
10494         decalsystem_t *decalsystem;
10495         qboolean dynamic;
10496         dp_model_t *model;
10497         const msurface_t *surface;
10498         const msurface_t *surfaces;
10499         const int *surfacelist;
10500         const texture_t *texture;
10501         int numtriangles;
10502         int numsurfacelist;
10503         int surfacelistindex;
10504         int surfaceindex;
10505         int triangleindex;
10506         float localorigin[3];
10507         float localnormal[3];
10508         float localmins[3];
10509         float localmaxs[3];
10510         float localsize;
10511         //float normal[3];
10512         float planes[6][4];
10513         float angles[3];
10514         bih_t *bih;
10515         int bih_triangles_count;
10516         int bih_triangles[256];
10517         int bih_surfaces[256];
10518
10519         decalsystem = &ent->decalsystem;
10520         model = ent->model;
10521         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10522         {
10523                 R_DecalSystem_Reset(&ent->decalsystem);
10524                 return;
10525         }
10526
10527         if (!model->brush.data_leafs && !cl_decals_models.integer)
10528         {
10529                 if (decalsystem->model)
10530                         R_DecalSystem_Reset(decalsystem);
10531                 return;
10532         }
10533
10534         if (decalsystem->model != model)
10535                 R_DecalSystem_Reset(decalsystem);
10536         decalsystem->model = model;
10537
10538         RSurf_ActiveModelEntity(ent, true, false, false);
10539
10540         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10541         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10542         VectorNormalize(localnormal);
10543         localsize = worldsize*rsurface.inversematrixscale;
10544         localmins[0] = localorigin[0] - localsize;
10545         localmins[1] = localorigin[1] - localsize;
10546         localmins[2] = localorigin[2] - localsize;
10547         localmaxs[0] = localorigin[0] + localsize;
10548         localmaxs[1] = localorigin[1] + localsize;
10549         localmaxs[2] = localorigin[2] + localsize;
10550
10551         //VectorCopy(localnormal, planes[4]);
10552         //VectorVectors(planes[4], planes[2], planes[0]);
10553         AnglesFromVectors(angles, localnormal, NULL, false);
10554         AngleVectors(angles, planes[0], planes[2], planes[4]);
10555         VectorNegate(planes[0], planes[1]);
10556         VectorNegate(planes[2], planes[3]);
10557         VectorNegate(planes[4], planes[5]);
10558         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10559         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10560         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10561         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10562         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10563         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10564
10565 #if 1
10566 // works
10567 {
10568         matrix4x4_t forwardprojection;
10569         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10570         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10571 }
10572 #else
10573 // broken
10574 {
10575         float projectionvector[4][3];
10576         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10577         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10578         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10579         projectionvector[0][0] = planes[0][0] * ilocalsize;
10580         projectionvector[0][1] = planes[1][0] * ilocalsize;
10581         projectionvector[0][2] = planes[2][0] * ilocalsize;
10582         projectionvector[1][0] = planes[0][1] * ilocalsize;
10583         projectionvector[1][1] = planes[1][1] * ilocalsize;
10584         projectionvector[1][2] = planes[2][1] * ilocalsize;
10585         projectionvector[2][0] = planes[0][2] * ilocalsize;
10586         projectionvector[2][1] = planes[1][2] * ilocalsize;
10587         projectionvector[2][2] = planes[2][2] * ilocalsize;
10588         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10589         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10590         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10591         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10592 }
10593 #endif
10594
10595         dynamic = model->surfmesh.isanimated;
10596         numsurfacelist = model->nummodelsurfaces;
10597         surfacelist = model->sortedmodelsurfaces;
10598         surfaces = model->data_surfaces;
10599
10600         bih = NULL;
10601         bih_triangles_count = -1;
10602         if(!dynamic)
10603         {
10604                 if(model->render_bih.numleafs)
10605                         bih = &model->render_bih;
10606                 else if(model->collision_bih.numleafs)
10607                         bih = &model->collision_bih;
10608         }
10609         if(bih)
10610                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10611         if(bih_triangles_count == 0)
10612                 return;
10613         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10614                 return;
10615         if(bih_triangles_count > 0)
10616         {
10617                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10618                 {
10619                         surfaceindex = bih_surfaces[triangleindex];
10620                         surface = surfaces + surfaceindex;
10621                         texture = surface->texture;
10622                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10623                                 continue;
10624                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10625                                 continue;
10626                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10627                 }
10628         }
10629         else
10630         {
10631                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10632                 {
10633                         surfaceindex = surfacelist[surfacelistindex];
10634                         surface = surfaces + surfaceindex;
10635                         // check cull box first because it rejects more than any other check
10636                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10637                                 continue;
10638                         // skip transparent surfaces
10639                         texture = surface->texture;
10640                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10641                                 continue;
10642                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10643                                 continue;
10644                         numtriangles = surface->num_triangles;
10645                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10646                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10647                 }
10648         }
10649 }
10650
10651 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10652 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)
10653 {
10654         int renderentityindex;
10655         float worldmins[3];
10656         float worldmaxs[3];
10657         entity_render_t *ent;
10658
10659         if (!cl_decals_newsystem.integer)
10660                 return;
10661
10662         worldmins[0] = worldorigin[0] - worldsize;
10663         worldmins[1] = worldorigin[1] - worldsize;
10664         worldmins[2] = worldorigin[2] - worldsize;
10665         worldmaxs[0] = worldorigin[0] + worldsize;
10666         worldmaxs[1] = worldorigin[1] + worldsize;
10667         worldmaxs[2] = worldorigin[2] + worldsize;
10668
10669         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10670
10671         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10672         {
10673                 ent = r_refdef.scene.entities[renderentityindex];
10674                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10675                         continue;
10676
10677                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10678         }
10679 }
10680
10681 typedef struct r_decalsystem_splatqueue_s
10682 {
10683         vec3_t worldorigin;
10684         vec3_t worldnormal;
10685         float color[4];
10686         float tcrange[4];
10687         float worldsize;
10688         int decalsequence;
10689 }
10690 r_decalsystem_splatqueue_t;
10691
10692 int r_decalsystem_numqueued = 0;
10693 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10694
10695 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)
10696 {
10697         r_decalsystem_splatqueue_t *queue;
10698
10699         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10700                 return;
10701
10702         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10703         VectorCopy(worldorigin, queue->worldorigin);
10704         VectorCopy(worldnormal, queue->worldnormal);
10705         Vector4Set(queue->color, r, g, b, a);
10706         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10707         queue->worldsize = worldsize;
10708         queue->decalsequence = cl.decalsequence++;
10709 }
10710
10711 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10712 {
10713         int i;
10714         r_decalsystem_splatqueue_t *queue;
10715
10716         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10717                 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);
10718         r_decalsystem_numqueued = 0;
10719 }
10720
10721 extern cvar_t cl_decals_max;
10722 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10723 {
10724         int i;
10725         decalsystem_t *decalsystem = &ent->decalsystem;
10726         int numdecals;
10727         int killsequence;
10728         tridecal_t *decal;
10729         float frametime;
10730         float lifetime;
10731
10732         if (!decalsystem->numdecals)
10733                 return;
10734
10735         if (r_showsurfaces.integer)
10736                 return;
10737
10738         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10739         {
10740                 R_DecalSystem_Reset(decalsystem);
10741                 return;
10742         }
10743
10744         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10745         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10746
10747         if (decalsystem->lastupdatetime)
10748                 frametime = (cl.time - decalsystem->lastupdatetime);
10749         else
10750                 frametime = 0;
10751         decalsystem->lastupdatetime = cl.time;
10752         decal = decalsystem->decals;
10753         numdecals = decalsystem->numdecals;
10754
10755         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10756         {
10757                 if (decal->color4f[0][3])
10758                 {
10759                         decal->lived += frametime;
10760                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10761                         {
10762                                 memset(decal, 0, sizeof(*decal));
10763                                 if (decalsystem->freedecal > i)
10764                                         decalsystem->freedecal = i;
10765                         }
10766                 }
10767         }
10768         decal = decalsystem->decals;
10769         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10770                 numdecals--;
10771
10772         // collapse the array by shuffling the tail decals into the gaps
10773         for (;;)
10774         {
10775                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10776                         decalsystem->freedecal++;
10777                 if (decalsystem->freedecal == numdecals)
10778                         break;
10779                 decal[decalsystem->freedecal] = decal[--numdecals];
10780         }
10781
10782         decalsystem->numdecals = numdecals;
10783
10784         if (numdecals <= 0)
10785         {
10786                 // if there are no decals left, reset decalsystem
10787                 R_DecalSystem_Reset(decalsystem);
10788         }
10789 }
10790
10791 extern skinframe_t *decalskinframe;
10792 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10793 {
10794         int i;
10795         decalsystem_t *decalsystem = &ent->decalsystem;
10796         int numdecals;
10797         tridecal_t *decal;
10798         float faderate;
10799         float alpha;
10800         float *v3f;
10801         float *c4f;
10802         float *t2f;
10803         const int *e;
10804         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10805         int numtris = 0;
10806
10807         numdecals = decalsystem->numdecals;
10808         if (!numdecals)
10809                 return;
10810
10811         if (r_showsurfaces.integer)
10812                 return;
10813
10814         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10815         {
10816                 R_DecalSystem_Reset(decalsystem);
10817                 return;
10818         }
10819
10820         // if the model is static it doesn't matter what value we give for
10821         // wantnormals and wanttangents, so this logic uses only rules applicable
10822         // to a model, knowing that they are meaningless otherwise
10823         if (ent == r_refdef.scene.worldentity)
10824                 RSurf_ActiveWorldEntity();
10825         else
10826                 RSurf_ActiveModelEntity(ent, false, false, false);
10827
10828         decalsystem->lastupdatetime = cl.time;
10829         decal = decalsystem->decals;
10830
10831         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10832
10833         // update vertex positions for animated models
10834         v3f = decalsystem->vertex3f;
10835         c4f = decalsystem->color4f;
10836         t2f = decalsystem->texcoord2f;
10837         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10838         {
10839                 if (!decal->color4f[0][3])
10840                         continue;
10841
10842                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10843                         continue;
10844
10845                 // skip backfaces
10846                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10847                         continue;
10848
10849                 // update color values for fading decals
10850                 if (decal->lived >= cl_decals_time.value)
10851                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10852                 else
10853                         alpha = 1.0f;
10854
10855                 c4f[ 0] = decal->color4f[0][0] * alpha;
10856                 c4f[ 1] = decal->color4f[0][1] * alpha;
10857                 c4f[ 2] = decal->color4f[0][2] * alpha;
10858                 c4f[ 3] = 1;
10859                 c4f[ 4] = decal->color4f[1][0] * alpha;
10860                 c4f[ 5] = decal->color4f[1][1] * alpha;
10861                 c4f[ 6] = decal->color4f[1][2] * alpha;
10862                 c4f[ 7] = 1;
10863                 c4f[ 8] = decal->color4f[2][0] * alpha;
10864                 c4f[ 9] = decal->color4f[2][1] * alpha;
10865                 c4f[10] = decal->color4f[2][2] * alpha;
10866                 c4f[11] = 1;
10867
10868                 t2f[0] = decal->texcoord2f[0][0];
10869                 t2f[1] = decal->texcoord2f[0][1];
10870                 t2f[2] = decal->texcoord2f[1][0];
10871                 t2f[3] = decal->texcoord2f[1][1];
10872                 t2f[4] = decal->texcoord2f[2][0];
10873                 t2f[5] = decal->texcoord2f[2][1];
10874
10875                 // update vertex positions for animated models
10876                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10877                 {
10878                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10879                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10880                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10881                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10882                 }
10883                 else
10884                 {
10885                         VectorCopy(decal->vertex3f[0], v3f);
10886                         VectorCopy(decal->vertex3f[1], v3f + 3);
10887                         VectorCopy(decal->vertex3f[2], v3f + 6);
10888                 }
10889
10890                 if (r_refdef.fogenabled)
10891                 {
10892                         alpha = RSurf_FogVertex(v3f);
10893                         VectorScale(c4f, alpha, c4f);
10894                         alpha = RSurf_FogVertex(v3f + 3);
10895                         VectorScale(c4f + 4, alpha, c4f + 4);
10896                         alpha = RSurf_FogVertex(v3f + 6);
10897                         VectorScale(c4f + 8, alpha, c4f + 8);
10898                 }
10899
10900                 v3f += 9;
10901                 c4f += 12;
10902                 t2f += 6;
10903                 numtris++;
10904         }
10905
10906         if (numtris > 0)
10907         {
10908                 r_refdef.stats.drawndecals += numtris;
10909
10910                 // now render the decals all at once
10911                 // (this assumes they all use one particle font texture!)
10912                 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);
10913 //              R_Mesh_ResetTextureState();
10914                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10915                 GL_DepthMask(false);
10916                 GL_DepthRange(0, 1);
10917                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10918                 GL_DepthTest(true);
10919                 GL_CullFace(GL_NONE);
10920                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10921                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10922                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10923         }
10924 }
10925
10926 static void R_DrawModelDecals(void)
10927 {
10928         int i, numdecals;
10929
10930         // fade faster when there are too many decals
10931         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10932         for (i = 0;i < r_refdef.scene.numentities;i++)
10933                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10934
10935         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10936         for (i = 0;i < r_refdef.scene.numentities;i++)
10937                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10938                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10939
10940         R_DecalSystem_ApplySplatEntitiesQueue();
10941
10942         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10943         for (i = 0;i < r_refdef.scene.numentities;i++)
10944                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10945
10946         r_refdef.stats.totaldecals += numdecals;
10947
10948         if (r_showsurfaces.integer)
10949                 return;
10950
10951         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10952
10953         for (i = 0;i < r_refdef.scene.numentities;i++)
10954         {
10955                 if (!r_refdef.viewcache.entityvisible[i])
10956                         continue;
10957                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10958                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10959         }
10960 }
10961
10962 extern cvar_t mod_collision_bih;
10963 void R_DrawDebugModel(void)
10964 {
10965         entity_render_t *ent = rsurface.entity;
10966         int i, j, k, l, flagsmask;
10967         const msurface_t *surface;
10968         dp_model_t *model = ent->model;
10969         vec3_t v;
10970
10971         switch(vid.renderpath)
10972         {
10973         case RENDERPATH_GL11:
10974         case RENDERPATH_GL13:
10975         case RENDERPATH_GL20:
10976                 break;
10977         case RENDERPATH_D3D9:
10978                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10979                 return;
10980         case RENDERPATH_D3D10:
10981                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10982                 return;
10983         case RENDERPATH_D3D11:
10984                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10985                 return;
10986         case RENDERPATH_SOFT:
10987                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10988                 return;
10989         case RENDERPATH_GLES2:
10990                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10991                 return;
10992         }
10993
10994         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10995
10996 //      R_Mesh_ResetTextureState();
10997         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10998         GL_DepthRange(0, 1);
10999         GL_DepthTest(!r_showdisabledepthtest.integer);
11000         GL_DepthMask(false);
11001         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11002
11003         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11004         {
11005                 int triangleindex;
11006                 int bihleafindex;
11007                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11008                 const q3mbrush_t *brush;
11009                 const bih_t *bih = &model->collision_bih;
11010                 const bih_leaf_t *bihleaf;
11011                 float vertex3f[3][3];
11012                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11013                 cullbox = false;
11014                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11015                 {
11016                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11017                                 continue;
11018                         switch (bihleaf->type)
11019                         {
11020                         case BIH_BRUSH:
11021                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11022                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11023                                 {
11024                                         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);
11025                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11026                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11027                                 }
11028                                 break;
11029                         case BIH_COLLISIONTRIANGLE:
11030                                 triangleindex = bihleaf->itemindex;
11031                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11032                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11033                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11034                                 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);
11035                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11036                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11037                                 break;
11038                         case BIH_RENDERTRIANGLE:
11039                                 triangleindex = bihleaf->itemindex;
11040                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11041                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11042                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11043                                 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);
11044                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11045                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11046                                 break;
11047                         }
11048                 }
11049         }
11050
11051         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11052
11053         if (r_showtris.integer || (r_shownormals.value != 0))
11054         {
11055                 if (r_showdisabledepthtest.integer)
11056                 {
11057                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11058                         GL_DepthMask(false);
11059                 }
11060                 else
11061                 {
11062                         GL_BlendFunc(GL_ONE, GL_ZERO);
11063                         GL_DepthMask(true);
11064                 }
11065                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11066                 {
11067                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11068                                 continue;
11069                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11070                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11071                         {
11072                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11073                                 if (r_showtris.value > 0)
11074                                 {
11075                                         if (!rsurface.texture->currentlayers->depthmask)
11076                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11077                                         else if (ent == r_refdef.scene.worldentity)
11078                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11079                                         else
11080                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11081                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11082                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11083                                         RSurf_DrawBatch();
11084                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11085                                         CHECKGLERROR
11086                                 }
11087                                 if (r_shownormals.value < 0)
11088                                 {
11089                                         qglBegin(GL_LINES);
11090                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11091                                         {
11092                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11093                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11094                                                 qglVertex3f(v[0], v[1], v[2]);
11095                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11096                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11097                                                 qglVertex3f(v[0], v[1], v[2]);
11098                                         }
11099                                         qglEnd();
11100                                         CHECKGLERROR
11101                                 }
11102                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11103                                 {
11104                                         qglBegin(GL_LINES);
11105                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11106                                         {
11107                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11108                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11109                                                 qglVertex3f(v[0], v[1], v[2]);
11110                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11111                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11112                                                 qglVertex3f(v[0], v[1], v[2]);
11113                                         }
11114                                         qglEnd();
11115                                         CHECKGLERROR
11116                                         qglBegin(GL_LINES);
11117                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11118                                         {
11119                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11120                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11121                                                 qglVertex3f(v[0], v[1], v[2]);
11122                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11123                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11124                                                 qglVertex3f(v[0], v[1], v[2]);
11125                                         }
11126                                         qglEnd();
11127                                         CHECKGLERROR
11128                                         qglBegin(GL_LINES);
11129                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11130                                         {
11131                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11132                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11133                                                 qglVertex3f(v[0], v[1], v[2]);
11134                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11135                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11136                                                 qglVertex3f(v[0], v[1], v[2]);
11137                                         }
11138                                         qglEnd();
11139                                         CHECKGLERROR
11140                                 }
11141                         }
11142                 }
11143                 rsurface.texture = NULL;
11144         }
11145 }
11146
11147 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11148 int r_maxsurfacelist = 0;
11149 const msurface_t **r_surfacelist = NULL;
11150 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11151 {
11152         int i, j, endj, flagsmask;
11153         dp_model_t *model = r_refdef.scene.worldmodel;
11154         msurface_t *surfaces;
11155         unsigned char *update;
11156         int numsurfacelist = 0;
11157         if (model == NULL)
11158                 return;
11159
11160         if (r_maxsurfacelist < model->num_surfaces)
11161         {
11162                 r_maxsurfacelist = model->num_surfaces;
11163                 if (r_surfacelist)
11164                         Mem_Free((msurface_t**)r_surfacelist);
11165                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11166         }
11167
11168         RSurf_ActiveWorldEntity();
11169
11170         surfaces = model->data_surfaces;
11171         update = model->brushq1.lightmapupdateflags;
11172
11173         // update light styles on this submodel
11174         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11175         {
11176                 model_brush_lightstyleinfo_t *style;
11177                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11178                 {
11179                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11180                         {
11181                                 int *list = style->surfacelist;
11182                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11183                                 for (j = 0;j < style->numsurfaces;j++)
11184                                         update[list[j]] = true;
11185                         }
11186                 }
11187         }
11188
11189         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11190
11191         if (debug)
11192         {
11193                 R_DrawDebugModel();
11194                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11195                 return;
11196         }
11197
11198         rsurface.lightmaptexture = NULL;
11199         rsurface.deluxemaptexture = NULL;
11200         rsurface.uselightmaptexture = false;
11201         rsurface.texture = NULL;
11202         rsurface.rtlight = NULL;
11203         numsurfacelist = 0;
11204         // add visible surfaces to draw list
11205         for (i = 0;i < model->nummodelsurfaces;i++)
11206         {
11207                 j = model->sortedmodelsurfaces[i];
11208                 if (r_refdef.viewcache.world_surfacevisible[j])
11209                         r_surfacelist[numsurfacelist++] = surfaces + j;
11210         }
11211         // update lightmaps if needed
11212         if (model->brushq1.firstrender)
11213         {
11214                 model->brushq1.firstrender = false;
11215                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11216                         if (update[j])
11217                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11218         }
11219         else if (update)
11220         {
11221                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11222                         if (r_refdef.viewcache.world_surfacevisible[j])
11223                                 if (update[j])
11224                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11225         }
11226         // don't do anything if there were no surfaces
11227         if (!numsurfacelist)
11228         {
11229                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11230                 return;
11231         }
11232         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11233
11234         // add to stats if desired
11235         if (r_speeds.integer && !skysurfaces && !depthonly)
11236         {
11237                 r_refdef.stats.world_surfaces += numsurfacelist;
11238                 for (j = 0;j < numsurfacelist;j++)
11239                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11240         }
11241
11242         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11243 }
11244
11245 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11246 {
11247         int i, j, endj, flagsmask;
11248         dp_model_t *model = ent->model;
11249         msurface_t *surfaces;
11250         unsigned char *update;
11251         int numsurfacelist = 0;
11252         if (model == NULL)
11253                 return;
11254
11255         if (r_maxsurfacelist < model->num_surfaces)
11256         {
11257                 r_maxsurfacelist = model->num_surfaces;
11258                 if (r_surfacelist)
11259                         Mem_Free((msurface_t **)r_surfacelist);
11260                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11261         }
11262
11263         // if the model is static it doesn't matter what value we give for
11264         // wantnormals and wanttangents, so this logic uses only rules applicable
11265         // to a model, knowing that they are meaningless otherwise
11266         if (ent == r_refdef.scene.worldentity)
11267                 RSurf_ActiveWorldEntity();
11268         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11269                 RSurf_ActiveModelEntity(ent, false, false, false);
11270         else if (prepass)
11271                 RSurf_ActiveModelEntity(ent, true, true, true);
11272         else if (depthonly)
11273         {
11274                 switch (vid.renderpath)
11275                 {
11276                 case RENDERPATH_GL20:
11277                 case RENDERPATH_D3D9:
11278                 case RENDERPATH_D3D10:
11279                 case RENDERPATH_D3D11:
11280                 case RENDERPATH_SOFT:
11281                 case RENDERPATH_GLES2:
11282                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11283                         break;
11284                 case RENDERPATH_GL13:
11285                 case RENDERPATH_GL11:
11286                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11287                         break;
11288                 }
11289         }
11290         else
11291         {
11292                 switch (vid.renderpath)
11293                 {
11294                 case RENDERPATH_GL20:
11295                 case RENDERPATH_D3D9:
11296                 case RENDERPATH_D3D10:
11297                 case RENDERPATH_D3D11:
11298                 case RENDERPATH_SOFT:
11299                 case RENDERPATH_GLES2:
11300                         RSurf_ActiveModelEntity(ent, true, true, false);
11301                         break;
11302                 case RENDERPATH_GL13:
11303                 case RENDERPATH_GL11:
11304                         RSurf_ActiveModelEntity(ent, true, false, false);
11305                         break;
11306                 }
11307         }
11308
11309         surfaces = model->data_surfaces;
11310         update = model->brushq1.lightmapupdateflags;
11311
11312         // update light styles
11313         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11314         {
11315                 model_brush_lightstyleinfo_t *style;
11316                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11317                 {
11318                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11319                         {
11320                                 int *list = style->surfacelist;
11321                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11322                                 for (j = 0;j < style->numsurfaces;j++)
11323                                         update[list[j]] = true;
11324                         }
11325                 }
11326         }
11327
11328         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11329
11330         if (debug)
11331         {
11332                 R_DrawDebugModel();
11333                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11334                 return;
11335         }
11336
11337         rsurface.lightmaptexture = NULL;
11338         rsurface.deluxemaptexture = NULL;
11339         rsurface.uselightmaptexture = false;
11340         rsurface.texture = NULL;
11341         rsurface.rtlight = NULL;
11342         numsurfacelist = 0;
11343         // add visible surfaces to draw list
11344         for (i = 0;i < model->nummodelsurfaces;i++)
11345                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11346         // don't do anything if there were no surfaces
11347         if (!numsurfacelist)
11348         {
11349                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11350                 return;
11351         }
11352         // update lightmaps if needed
11353         if (update)
11354         {
11355                 int updated = 0;
11356                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11357                 {
11358                         if (update[j])
11359                         {
11360                                 updated++;
11361                                 R_BuildLightMap(ent, surfaces + j);
11362                         }
11363                 }
11364         }
11365         if (update)
11366                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11367                         if (update[j])
11368                                 R_BuildLightMap(ent, surfaces + j);
11369         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11370
11371         // add to stats if desired
11372         if (r_speeds.integer && !skysurfaces && !depthonly)
11373         {
11374                 r_refdef.stats.entities_surfaces += numsurfacelist;
11375                 for (j = 0;j < numsurfacelist;j++)
11376                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11377         }
11378
11379         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11380 }
11381
11382 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11383 {
11384         static texture_t texture;
11385         static msurface_t surface;
11386         const msurface_t *surfacelist = &surface;
11387
11388         // fake enough texture and surface state to render this geometry
11389
11390         texture.update_lastrenderframe = -1; // regenerate this texture
11391         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11392         texture.currentskinframe = skinframe;
11393         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11394         texture.offsetmapping = OFFSETMAPPING_OFF;
11395         texture.offsetscale = 1;
11396         texture.specularscalemod = 1;
11397         texture.specularpowermod = 1;
11398
11399         surface.texture = &texture;
11400         surface.num_triangles = numtriangles;
11401         surface.num_firsttriangle = firsttriangle;
11402         surface.num_vertices = numvertices;
11403         surface.num_firstvertex = firstvertex;
11404
11405         // now render it
11406         rsurface.texture = R_GetCurrentTexture(surface.texture);
11407         rsurface.lightmaptexture = NULL;
11408         rsurface.deluxemaptexture = NULL;
11409         rsurface.uselightmaptexture = false;
11410         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11411 }
11412
11413 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)
11414 {
11415         static msurface_t surface;
11416         const msurface_t *surfacelist = &surface;
11417
11418         // fake enough texture and surface state to render this geometry
11419         surface.texture = texture;
11420         surface.num_triangles = numtriangles;
11421         surface.num_firsttriangle = firsttriangle;
11422         surface.num_vertices = numvertices;
11423         surface.num_firstvertex = firstvertex;
11424
11425         // now render it
11426         rsurface.texture = R_GetCurrentTexture(surface.texture);
11427         rsurface.lightmaptexture = NULL;
11428         rsurface.deluxemaptexture = NULL;
11429         rsurface.uselightmaptexture = false;
11430         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11431 }