]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
reworked userdir path selection, now has 4 "tiers":
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
76 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
77 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)"};
78 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
79 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
80 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"};
81 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"};
82 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
83 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"};
84 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"};
85 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"};
86 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
87 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
88 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
89 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
90 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
91 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
92 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
93 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)"};
94 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)"};
95 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
96 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
97 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
98 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
99
100 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
101 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
102 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
103
104 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
105 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
106 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
107 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."};
108 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
109 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
110 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
111 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."};
112 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
113 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
114 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
115 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
116 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"};
117 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"};
118 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
119 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
121 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
122 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
123 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"};
124
125 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
126 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
127 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
128 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
129 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
130 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
131 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
132 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
133
134 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)"};
135 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"};
136
137 cvar_t r_texture_sRGB_2d = {0, "r_texture_sRGB_2d", "0", "load textures as sRGB"};
138 cvar_t r_texture_sRGB_skin_diffuse = {0, "r_texture_sRGB_skin_diffuse", "0", "load textures as sRGB"};
139 cvar_t r_texture_sRGB_skin_gloss = {0, "r_texture_sRGB_skin_gloss", "0", "load textures as sRGB"};
140 cvar_t r_texture_sRGB_skin_glow = {0, "r_texture_sRGB_skin_glow", "0", "load textures as sRGB"};
141 cvar_t r_texture_sRGB_skin_reflect = {0, "r_texture_sRGB_skin_reflect", "0", "load textures as sRGB"};
142 cvar_t r_texture_sRGB_cubemap = {0, "r_texture_sRGB_cubemap", "0", "load textures as sRGB"};
143 cvar_t r_texture_sRGB_skybox = {0, "r_texture_sRGB_skybox", "0", "load textures as sRGB"};
144
145 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
146 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
147 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
148
149 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"};
150 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"};
151 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
152 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
153 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"};
154 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)"};
155 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)"};
156 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
157
158 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)"};
159 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
160 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)"};
161 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
162 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)"};
163 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
164 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
165 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174
175 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)"};
176 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
177 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"};
178 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
179 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
180 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
181
182 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
183 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
184 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
185 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
186
187 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
188 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
189 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
190 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
191 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
192 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
193 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
194
195 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
196 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
197 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
198 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)"};
199 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
200 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
201 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
202 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
203 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
204 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
205
206 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"};
207
208 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"};
209
210 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
211
212 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
213 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"};
214 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
215 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
216 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
217 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
218 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)"};
219 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
220 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
221
222 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
223 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"};
224
225 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."};
226
227 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)"};
228
229 extern cvar_t v_glslgamma;
230
231 extern qboolean v_flipped_state;
232
233 static struct r_bloomstate_s
234 {
235         qboolean enabled;
236         qboolean hdr;
237
238         int bloomwidth, bloomheight;
239
240         textype_t texturetype;
241         int viewfbo; // used to check if r_viewfbo cvar has changed
242
243         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
244         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
245         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
246
247         int screentexturewidth, screentextureheight;
248         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
249
250         int bloomtexturewidth, bloomtextureheight;
251         rtexture_t *texture_bloom;
252
253         // arrays for rendering the screen passes
254         float screentexcoord2f[8];
255         float bloomtexcoord2f[8];
256         float offsettexcoord2f[8];
257
258         r_viewport_t viewport;
259 }
260 r_bloomstate;
261
262 r_waterstate_t r_waterstate;
263
264 /// shadow volume bsp struct with automatically growing nodes buffer
265 svbsp_t r_svbsp;
266
267 rtexture_t *r_texture_blanknormalmap;
268 rtexture_t *r_texture_white;
269 rtexture_t *r_texture_grey128;
270 rtexture_t *r_texture_black;
271 rtexture_t *r_texture_notexture;
272 rtexture_t *r_texture_whitecube;
273 rtexture_t *r_texture_normalizationcube;
274 rtexture_t *r_texture_fogattenuation;
275 rtexture_t *r_texture_fogheighttexture;
276 rtexture_t *r_texture_gammaramps;
277 unsigned int r_texture_gammaramps_serial;
278 //rtexture_t *r_texture_fogintensity;
279 rtexture_t *r_texture_reflectcube;
280
281 // TODO: hash lookups?
282 typedef struct cubemapinfo_s
283 {
284         char basename[64];
285         rtexture_t *texture;
286 }
287 cubemapinfo_t;
288
289 int r_texture_numcubemaps;
290 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
291
292 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
293 unsigned int r_numqueries;
294 unsigned int r_maxqueries;
295
296 typedef struct r_qwskincache_s
297 {
298         char name[MAX_QPATH];
299         skinframe_t *skinframe;
300 }
301 r_qwskincache_t;
302
303 static r_qwskincache_t *r_qwskincache;
304 static int r_qwskincache_size;
305
306 /// vertex coordinates for a quad that covers the screen exactly
307 extern const float r_screenvertex3f[12];
308 extern const float r_d3dscreenvertex3f[12];
309 const float r_screenvertex3f[12] =
310 {
311         0, 0, 0,
312         1, 0, 0,
313         1, 1, 0,
314         0, 1, 0
315 };
316 const float r_d3dscreenvertex3f[12] =
317 {
318         0, 1, 0,
319         1, 1, 0,
320         1, 0, 0,
321         0, 0, 0
322 };
323
324 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
325 {
326         int i;
327         for (i = 0;i < verts;i++)
328         {
329                 out[0] = in[0] * r;
330                 out[1] = in[1] * g;
331                 out[2] = in[2] * b;
332                 out[3] = in[3];
333                 in += 4;
334                 out += 4;
335         }
336 }
337
338 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
339 {
340         int i;
341         for (i = 0;i < verts;i++)
342         {
343                 out[0] = r;
344                 out[1] = g;
345                 out[2] = b;
346                 out[3] = a;
347                 out += 4;
348         }
349 }
350
351 // FIXME: move this to client?
352 void FOG_clear(void)
353 {
354         if (gamemode == GAME_NEHAHRA)
355         {
356                 Cvar_Set("gl_fogenable", "0");
357                 Cvar_Set("gl_fogdensity", "0.2");
358                 Cvar_Set("gl_fogred", "0.3");
359                 Cvar_Set("gl_foggreen", "0.3");
360                 Cvar_Set("gl_fogblue", "0.3");
361         }
362         r_refdef.fog_density = 0;
363         r_refdef.fog_red = 0;
364         r_refdef.fog_green = 0;
365         r_refdef.fog_blue = 0;
366         r_refdef.fog_alpha = 1;
367         r_refdef.fog_start = 0;
368         r_refdef.fog_end = 16384;
369         r_refdef.fog_height = 1<<30;
370         r_refdef.fog_fadedepth = 128;
371         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
372 }
373
374 static void R_BuildBlankTextures(void)
375 {
376         unsigned char data[4];
377         data[2] = 128; // normal X
378         data[1] = 128; // normal Y
379         data[0] = 255; // normal Z
380         data[3] = 128; // height
381         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
382         data[0] = 255;
383         data[1] = 255;
384         data[2] = 255;
385         data[3] = 255;
386         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
387         data[0] = 128;
388         data[1] = 128;
389         data[2] = 128;
390         data[3] = 255;
391         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392         data[0] = 0;
393         data[1] = 0;
394         data[2] = 0;
395         data[3] = 255;
396         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
397 }
398
399 static void R_BuildNoTexture(void)
400 {
401         int x, y;
402         unsigned char pix[16][16][4];
403         // this makes a light grey/dark grey checkerboard texture
404         for (y = 0;y < 16;y++)
405         {
406                 for (x = 0;x < 16;x++)
407                 {
408                         if ((y < 8) ^ (x < 8))
409                         {
410                                 pix[y][x][0] = 128;
411                                 pix[y][x][1] = 128;
412                                 pix[y][x][2] = 128;
413                                 pix[y][x][3] = 255;
414                         }
415                         else
416                         {
417                                 pix[y][x][0] = 64;
418                                 pix[y][x][1] = 64;
419                                 pix[y][x][2] = 64;
420                                 pix[y][x][3] = 255;
421                         }
422                 }
423         }
424         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
425 }
426
427 static void R_BuildWhiteCube(void)
428 {
429         unsigned char data[6*1*1*4];
430         memset(data, 255, sizeof(data));
431         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
432 }
433
434 static void R_BuildNormalizationCube(void)
435 {
436         int x, y, side;
437         vec3_t v;
438         vec_t s, t, intensity;
439 #define NORMSIZE 64
440         unsigned char *data;
441         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
442         for (side = 0;side < 6;side++)
443         {
444                 for (y = 0;y < NORMSIZE;y++)
445                 {
446                         for (x = 0;x < NORMSIZE;x++)
447                         {
448                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
449                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
450                                 switch(side)
451                                 {
452                                 default:
453                                 case 0:
454                                         v[0] = 1;
455                                         v[1] = -t;
456                                         v[2] = -s;
457                                         break;
458                                 case 1:
459                                         v[0] = -1;
460                                         v[1] = -t;
461                                         v[2] = s;
462                                         break;
463                                 case 2:
464                                         v[0] = s;
465                                         v[1] = 1;
466                                         v[2] = t;
467                                         break;
468                                 case 3:
469                                         v[0] = s;
470                                         v[1] = -1;
471                                         v[2] = -t;
472                                         break;
473                                 case 4:
474                                         v[0] = s;
475                                         v[1] = -t;
476                                         v[2] = 1;
477                                         break;
478                                 case 5:
479                                         v[0] = -s;
480                                         v[1] = -t;
481                                         v[2] = -1;
482                                         break;
483                                 }
484                                 intensity = 127.0f / sqrt(DotProduct(v, v));
485                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
486                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
487                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
488                                 data[((side*64+y)*64+x)*4+3] = 255;
489                         }
490                 }
491         }
492         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
493         Mem_Free(data);
494 }
495
496 static void R_BuildFogTexture(void)
497 {
498         int x, b;
499 #define FOGWIDTH 256
500         unsigned char data1[FOGWIDTH][4];
501         //unsigned char data2[FOGWIDTH][4];
502         double d, r, alpha;
503
504         r_refdef.fogmasktable_start = r_refdef.fog_start;
505         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
506         r_refdef.fogmasktable_range = r_refdef.fogrange;
507         r_refdef.fogmasktable_density = r_refdef.fog_density;
508
509         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
510         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
511         {
512                 d = (x * r - r_refdef.fogmasktable_start);
513                 if(developer_extra.integer)
514                         Con_DPrintf("%f ", d);
515                 d = max(0, d);
516                 if (r_fog_exp2.integer)
517                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
518                 else
519                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
520                 if(developer_extra.integer)
521                         Con_DPrintf(" : %f ", alpha);
522                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
523                 if(developer_extra.integer)
524                         Con_DPrintf(" = %f\n", alpha);
525                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
526         }
527
528         for (x = 0;x < FOGWIDTH;x++)
529         {
530                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
531                 data1[x][0] = b;
532                 data1[x][1] = b;
533                 data1[x][2] = b;
534                 data1[x][3] = 255;
535                 //data2[x][0] = 255 - b;
536                 //data2[x][1] = 255 - b;
537                 //data2[x][2] = 255 - b;
538                 //data2[x][3] = 255;
539         }
540         if (r_texture_fogattenuation)
541         {
542                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
543                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
544         }
545         else
546         {
547                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
548                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
549         }
550 }
551
552 static void R_BuildFogHeightTexture(void)
553 {
554         unsigned char *inpixels;
555         int size;
556         int x;
557         int y;
558         int j;
559         float c[4];
560         float f;
561         inpixels = NULL;
562         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
563         if (r_refdef.fogheighttexturename[0])
564                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
565         if (!inpixels)
566         {
567                 r_refdef.fog_height_tablesize = 0;
568                 if (r_texture_fogheighttexture)
569                         R_FreeTexture(r_texture_fogheighttexture);
570                 r_texture_fogheighttexture = NULL;
571                 if (r_refdef.fog_height_table2d)
572                         Mem_Free(r_refdef.fog_height_table2d);
573                 r_refdef.fog_height_table2d = NULL;
574                 if (r_refdef.fog_height_table1d)
575                         Mem_Free(r_refdef.fog_height_table1d);
576                 r_refdef.fog_height_table1d = NULL;
577                 return;
578         }
579         size = image_width;
580         r_refdef.fog_height_tablesize = size;
581         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
582         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
583         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
584         Mem_Free(inpixels);
585         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
586         // average fog color table accounting for every fog layer between a point
587         // and the camera.  (Note: attenuation is handled separately!)
588         for (y = 0;y < size;y++)
589         {
590                 for (x = 0;x < size;x++)
591                 {
592                         Vector4Clear(c);
593                         f = 0;
594                         if (x < y)
595                         {
596                                 for (j = x;j <= y;j++)
597                                 {
598                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
599                                         f++;
600                                 }
601                         }
602                         else
603                         {
604                                 for (j = x;j >= y;j--)
605                                 {
606                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
607                                         f++;
608                                 }
609                         }
610                         f = 1.0f / f;
611                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
612                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
613                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
614                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
615                 }
616         }
617         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
618 }
619
620 //=======================================================================================================================================================
621
622 static const char *builtinshaderstring =
623 #include "shader_glsl.h"
624 ;
625
626 const char *builtinhlslshaderstring =
627 #include "shader_hlsl.h"
628 ;
629
630 char *glslshaderstring = NULL;
631 char *hlslshaderstring = NULL;
632
633 //=======================================================================================================================================================
634
635 typedef struct shaderpermutationinfo_s
636 {
637         const char *pretext;
638         const char *name;
639 }
640 shaderpermutationinfo_t;
641
642 typedef struct shadermodeinfo_s
643 {
644         const char *vertexfilename;
645         const char *geometryfilename;
646         const char *fragmentfilename;
647         const char *pretext;
648         const char *name;
649 }
650 shadermodeinfo_t;
651
652 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
653 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
654 {
655         {"#define USEDIFFUSE\n", " diffuse"},
656         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
657         {"#define USEVIEWTINT\n", " viewtint"},
658         {"#define USECOLORMAPPING\n", " colormapping"},
659         {"#define USESATURATION\n", " saturation"},
660         {"#define USEFOGINSIDE\n", " foginside"},
661         {"#define USEFOGOUTSIDE\n", " fogoutside"},
662         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
663         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
664         {"#define USEGAMMARAMPS\n", " gammaramps"},
665         {"#define USECUBEFILTER\n", " cubefilter"},
666         {"#define USEGLOW\n", " glow"},
667         {"#define USEBLOOM\n", " bloom"},
668         {"#define USESPECULAR\n", " specular"},
669         {"#define USEPOSTPROCESSING\n", " postprocessing"},
670         {"#define USEREFLECTION\n", " reflection"},
671         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
672         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
673         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
674         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
675         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
676         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
677         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
678         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
679         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
680         {"#define USEALPHAKILL\n", " alphakill"},
681         {"#define USEREFLECTCUBE\n", " reflectcube"},
682         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
683         {"#define USEBOUNCEGRID\n", " bouncegrid"},
684         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
685 };
686
687 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
688 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
689 {
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
692         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
704         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
705         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 };
707
708 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
709 {
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
725         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
726 };
727
728 struct r_glsl_permutation_s;
729 typedef struct r_glsl_permutation_s
730 {
731         /// hash lookup data
732         struct r_glsl_permutation_s *hashnext;
733         unsigned int mode;
734         unsigned int permutation;
735
736         /// indicates if we have tried compiling this permutation already
737         qboolean compiled;
738         /// 0 if compilation failed
739         int program;
740         // texture units assigned to each detected uniform
741         int tex_Texture_First;
742         int tex_Texture_Second;
743         int tex_Texture_GammaRamps;
744         int tex_Texture_Normal;
745         int tex_Texture_Color;
746         int tex_Texture_Gloss;
747         int tex_Texture_Glow;
748         int tex_Texture_SecondaryNormal;
749         int tex_Texture_SecondaryColor;
750         int tex_Texture_SecondaryGloss;
751         int tex_Texture_SecondaryGlow;
752         int tex_Texture_Pants;
753         int tex_Texture_Shirt;
754         int tex_Texture_FogHeightTexture;
755         int tex_Texture_FogMask;
756         int tex_Texture_Lightmap;
757         int tex_Texture_Deluxemap;
758         int tex_Texture_Attenuation;
759         int tex_Texture_Cube;
760         int tex_Texture_Refraction;
761         int tex_Texture_Reflection;
762         int tex_Texture_ShadowMap2D;
763         int tex_Texture_CubeProjection;
764         int tex_Texture_ScreenDepth;
765         int tex_Texture_ScreenNormalMap;
766         int tex_Texture_ScreenDiffuse;
767         int tex_Texture_ScreenSpecular;
768         int tex_Texture_ReflectMask;
769         int tex_Texture_ReflectCube;
770         int tex_Texture_BounceGrid;
771         /// locations of detected uniforms in program object, or -1 if not found
772         int loc_Texture_First;
773         int loc_Texture_Second;
774         int loc_Texture_GammaRamps;
775         int loc_Texture_Normal;
776         int loc_Texture_Color;
777         int loc_Texture_Gloss;
778         int loc_Texture_Glow;
779         int loc_Texture_SecondaryNormal;
780         int loc_Texture_SecondaryColor;
781         int loc_Texture_SecondaryGloss;
782         int loc_Texture_SecondaryGlow;
783         int loc_Texture_Pants;
784         int loc_Texture_Shirt;
785         int loc_Texture_FogHeightTexture;
786         int loc_Texture_FogMask;
787         int loc_Texture_Lightmap;
788         int loc_Texture_Deluxemap;
789         int loc_Texture_Attenuation;
790         int loc_Texture_Cube;
791         int loc_Texture_Refraction;
792         int loc_Texture_Reflection;
793         int loc_Texture_ShadowMap2D;
794         int loc_Texture_CubeProjection;
795         int loc_Texture_ScreenDepth;
796         int loc_Texture_ScreenNormalMap;
797         int loc_Texture_ScreenDiffuse;
798         int loc_Texture_ScreenSpecular;
799         int loc_Texture_ReflectMask;
800         int loc_Texture_ReflectCube;
801         int loc_Texture_BounceGrid;
802         int loc_Alpha;
803         int loc_BloomBlur_Parameters;
804         int loc_ClientTime;
805         int loc_Color_Ambient;
806         int loc_Color_Diffuse;
807         int loc_Color_Specular;
808         int loc_Color_Glow;
809         int loc_Color_Pants;
810         int loc_Color_Shirt;
811         int loc_DeferredColor_Ambient;
812         int loc_DeferredColor_Diffuse;
813         int loc_DeferredColor_Specular;
814         int loc_DeferredMod_Diffuse;
815         int loc_DeferredMod_Specular;
816         int loc_DistortScaleRefractReflect;
817         int loc_EyePosition;
818         int loc_FogColor;
819         int loc_FogHeightFade;
820         int loc_FogPlane;
821         int loc_FogPlaneViewDist;
822         int loc_FogRangeRecip;
823         int loc_LightColor;
824         int loc_LightDir;
825         int loc_LightPosition;
826         int loc_OffsetMapping_ScaleSteps;
827         int loc_PixelSize;
828         int loc_ReflectColor;
829         int loc_ReflectFactor;
830         int loc_ReflectOffset;
831         int loc_RefractColor;
832         int loc_Saturation;
833         int loc_ScreenCenterRefractReflect;
834         int loc_ScreenScaleRefractReflect;
835         int loc_ScreenToDepth;
836         int loc_ShadowMap_Parameters;
837         int loc_ShadowMap_TextureScale;
838         int loc_SpecularPower;
839         int loc_UserVec1;
840         int loc_UserVec2;
841         int loc_UserVec3;
842         int loc_UserVec4;
843         int loc_ViewTintColor;
844         int loc_ViewToLight;
845         int loc_ModelToLight;
846         int loc_TexMatrix;
847         int loc_BackgroundTexMatrix;
848         int loc_ModelViewProjectionMatrix;
849         int loc_ModelViewMatrix;
850         int loc_PixelToScreenTexCoord;
851         int loc_ModelToReflectCube;
852         int loc_ShadowMapMatrix;
853         int loc_BloomColorSubtract;
854         int loc_NormalmapScrollBlend;
855         int loc_BounceGridMatrix;
856         int loc_BounceGridIntensity;
857 }
858 r_glsl_permutation_t;
859
860 #define SHADERPERMUTATION_HASHSIZE 256
861
862
863 // non-degradable "lightweight" shader parameters to keep the permutations simpler
864 // these can NOT degrade! only use for simple stuff
865 enum
866 {
867         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
868         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
869         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
870         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
871         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
872         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
873         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
874 };
875 #define SHADERSTATICPARMS_COUNT 7
876
877 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
878 static int shaderstaticparms_count = 0;
879
880 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
881 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
882 qboolean R_CompileShader_CheckStaticParms(void)
883 {
884         static int r_compileshader_staticparms_save[1];
885         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
886         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
887
888         // detect all
889         if (r_glsl_saturation_redcompensate.integer)
890                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
891         if (r_glsl_vertextextureblend_usebothalphas.integer)
892                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
893         if (r_shadow_glossexact.integer)
894                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
895         if (r_glsl_postprocess.integer)
896         {
897                 if (r_glsl_postprocess_uservec1_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
899                 if (r_glsl_postprocess_uservec2_enable.integer)
900                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
901                 if (r_glsl_postprocess_uservec3_enable.integer)
902                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
903                 if (r_glsl_postprocess_uservec4_enable.integer)
904                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
905         }
906         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
907 }
908
909 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
910         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
911                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
912         else \
913                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
914 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
915 {
916         shaderstaticparms_count = 0;
917
918         // emit all
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
925         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
926 }
927
928 /// information about each possible shader permutation
929 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
930 /// currently selected permutation
931 r_glsl_permutation_t *r_glsl_permutation;
932 /// storage for permutations linked in the hash table
933 memexpandablearray_t r_glsl_permutationarray;
934
935 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
936 {
937         //unsigned int hashdepth = 0;
938         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
939         r_glsl_permutation_t *p;
940         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
941         {
942                 if (p->mode == mode && p->permutation == permutation)
943                 {
944                         //if (hashdepth > 10)
945                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
946                         return p;
947                 }
948                 //hashdepth++;
949         }
950         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
951         p->mode = mode;
952         p->permutation = permutation;
953         p->hashnext = r_glsl_permutationhash[mode][hashindex];
954         r_glsl_permutationhash[mode][hashindex] = p;
955         //if (hashdepth > 10)
956         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
957         return p;
958 }
959
960 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
961 {
962         char *shaderstring;
963         if (!filename || !filename[0])
964                 return NULL;
965         if (!strcmp(filename, "glsl/default.glsl"))
966         {
967                 if (!glslshaderstring)
968                 {
969                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
970                         if (glslshaderstring)
971                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
972                         else
973                                 glslshaderstring = (char *)builtinshaderstring;
974                 }
975                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
976                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
977                 return shaderstring;
978         }
979         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
980         if (shaderstring)
981         {
982                 if (printfromdisknotice)
983                         Con_DPrintf("from disk %s... ", filename);
984                 return shaderstring;
985         }
986         return shaderstring;
987 }
988
989 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
990 {
991         int i;
992         int sampler;
993         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
994         char *vertexstring, *geometrystring, *fragmentstring;
995         char permutationname[256];
996         int vertstrings_count = 0;
997         int geomstrings_count = 0;
998         int fragstrings_count = 0;
999         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1000         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1001         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1002
1003         if (p->compiled)
1004                 return;
1005         p->compiled = true;
1006         p->program = 0;
1007
1008         permutationname[0] = 0;
1009         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1010         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1011         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1012
1013         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1014
1015         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1016         if(vid.support.gl20shaders130)
1017         {
1018                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1019                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1020                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1021                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1022                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1023                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1024         }
1025
1026         // the first pretext is which type of shader to compile as
1027         // (later these will all be bound together as a program object)
1028         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1029         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1030         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1031
1032         // the second pretext is the mode (for example a light source)
1033         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1034         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1035         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1036         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1037
1038         // now add all the permutation pretexts
1039         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1040         {
1041                 if (permutation & (1<<i))
1042                 {
1043                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1044                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1045                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1046                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1047                 }
1048                 else
1049                 {
1050                         // keep line numbers correct
1051                         vertstrings_list[vertstrings_count++] = "\n";
1052                         geomstrings_list[geomstrings_count++] = "\n";
1053                         fragstrings_list[fragstrings_count++] = "\n";
1054                 }
1055         }
1056
1057         // add static parms
1058         R_CompileShader_AddStaticParms(mode, permutation);
1059         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1060         vertstrings_count += shaderstaticparms_count;
1061         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1062         geomstrings_count += shaderstaticparms_count;
1063         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1064         fragstrings_count += shaderstaticparms_count;
1065
1066         // now append the shader text itself
1067         vertstrings_list[vertstrings_count++] = vertexstring;
1068         geomstrings_list[geomstrings_count++] = geometrystring;
1069         fragstrings_list[fragstrings_count++] = fragmentstring;
1070
1071         // if any sources were NULL, clear the respective list
1072         if (!vertexstring)
1073                 vertstrings_count = 0;
1074         if (!geometrystring)
1075                 geomstrings_count = 0;
1076         if (!fragmentstring)
1077                 fragstrings_count = 0;
1078
1079         // compile the shader program
1080         if (vertstrings_count + geomstrings_count + fragstrings_count)
1081                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1082         if (p->program)
1083         {
1084                 CHECKGLERROR
1085                 qglUseProgram(p->program);CHECKGLERROR
1086                 // look up all the uniform variable names we care about, so we don't
1087                 // have to look them up every time we set them
1088
1089                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1090                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1091                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1092                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1093                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1094                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1095                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1096                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1097                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1098                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1099                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1100                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1101                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1102                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1103                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1104                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1105                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1106                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1107                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1108                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1109                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1110                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1111                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1112                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1113                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1114                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1115                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1116                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1117                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1118                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1119                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1120                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1121                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1122                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1123                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1124                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1125                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1126                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1127                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1128                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1129                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1130                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1131                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1132                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1133                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1134                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1135                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1136                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1137                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1138                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1139                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1140                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1141                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1142                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1143                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1144                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1145                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1146                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1147                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1148                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1149                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1150                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1151                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1152                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1153                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1154                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1155                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1156                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1157                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1158                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1159                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1160                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1161                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1162                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1163                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1164                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1165                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1166                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1167                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1168                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1169                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1170                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1171                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1172                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1173                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1174                 // initialize the samplers to refer to the texture units we use
1175                 p->tex_Texture_First = -1;
1176                 p->tex_Texture_Second = -1;
1177                 p->tex_Texture_GammaRamps = -1;
1178                 p->tex_Texture_Normal = -1;
1179                 p->tex_Texture_Color = -1;
1180                 p->tex_Texture_Gloss = -1;
1181                 p->tex_Texture_Glow = -1;
1182                 p->tex_Texture_SecondaryNormal = -1;
1183                 p->tex_Texture_SecondaryColor = -1;
1184                 p->tex_Texture_SecondaryGloss = -1;
1185                 p->tex_Texture_SecondaryGlow = -1;
1186                 p->tex_Texture_Pants = -1;
1187                 p->tex_Texture_Shirt = -1;
1188                 p->tex_Texture_FogHeightTexture = -1;
1189                 p->tex_Texture_FogMask = -1;
1190                 p->tex_Texture_Lightmap = -1;
1191                 p->tex_Texture_Deluxemap = -1;
1192                 p->tex_Texture_Attenuation = -1;
1193                 p->tex_Texture_Cube = -1;
1194                 p->tex_Texture_Refraction = -1;
1195                 p->tex_Texture_Reflection = -1;
1196                 p->tex_Texture_ShadowMap2D = -1;
1197                 p->tex_Texture_CubeProjection = -1;
1198                 p->tex_Texture_ScreenDepth = -1;
1199                 p->tex_Texture_ScreenNormalMap = -1;
1200                 p->tex_Texture_ScreenDiffuse = -1;
1201                 p->tex_Texture_ScreenSpecular = -1;
1202                 p->tex_Texture_ReflectMask = -1;
1203                 p->tex_Texture_ReflectCube = -1;
1204                 p->tex_Texture_BounceGrid = -1;
1205                 sampler = 0;
1206                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1207                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1208                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1209                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1210                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1211                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1212                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1213                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1214                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1215                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1216                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1217                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1218                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1219                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1220                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1221                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1222                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1223                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1224                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1225                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1226                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1227                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1228                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1229                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1230                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1231                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1232                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1233                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1234                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1235                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1236                 CHECKGLERROR
1237                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1238         }
1239         else
1240                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1241
1242         // free the strings
1243         if (vertexstring)
1244                 Mem_Free(vertexstring);
1245         if (geometrystring)
1246                 Mem_Free(geometrystring);
1247         if (fragmentstring)
1248                 Mem_Free(fragmentstring);
1249 }
1250
1251 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1252 {
1253         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1254         if (r_glsl_permutation != perm)
1255         {
1256                 r_glsl_permutation = perm;
1257                 if (!r_glsl_permutation->program)
1258                 {
1259                         if (!r_glsl_permutation->compiled)
1260                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1261                         if (!r_glsl_permutation->program)
1262                         {
1263                                 // remove features until we find a valid permutation
1264                                 int i;
1265                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1266                                 {
1267                                         // reduce i more quickly whenever it would not remove any bits
1268                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1269                                         if (!(permutation & j))
1270                                                 continue;
1271                                         permutation -= j;
1272                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1273                                         if (!r_glsl_permutation->compiled)
1274                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1275                                         if (r_glsl_permutation->program)
1276                                                 break;
1277                                 }
1278                                 if (i >= SHADERPERMUTATION_COUNT)
1279                                 {
1280                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1281                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1282                                         qglUseProgram(0);CHECKGLERROR
1283                                         return; // no bit left to clear, entire mode is broken
1284                                 }
1285                         }
1286                 }
1287                 CHECKGLERROR
1288                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1289         }
1290         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1291         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1292         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1293 }
1294
1295 #ifdef SUPPORTD3D
1296
1297 #ifdef SUPPORTD3D
1298 #include <d3d9.h>
1299 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1300 extern D3DCAPS9 vid_d3d9caps;
1301 #endif
1302
1303 struct r_hlsl_permutation_s;
1304 typedef struct r_hlsl_permutation_s
1305 {
1306         /// hash lookup data
1307         struct r_hlsl_permutation_s *hashnext;
1308         unsigned int mode;
1309         unsigned int permutation;
1310
1311         /// indicates if we have tried compiling this permutation already
1312         qboolean compiled;
1313         /// NULL if compilation failed
1314         IDirect3DVertexShader9 *vertexshader;
1315         IDirect3DPixelShader9 *pixelshader;
1316 }
1317 r_hlsl_permutation_t;
1318
1319 typedef enum D3DVSREGISTER_e
1320 {
1321         D3DVSREGISTER_TexMatrix = 0, // float4x4
1322         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1323         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1324         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1325         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1326         D3DVSREGISTER_ModelToLight = 20, // float4x4
1327         D3DVSREGISTER_EyePosition = 24,
1328         D3DVSREGISTER_FogPlane = 25,
1329         D3DVSREGISTER_LightDir = 26,
1330         D3DVSREGISTER_LightPosition = 27,
1331 }
1332 D3DVSREGISTER_t;
1333
1334 typedef enum D3DPSREGISTER_e
1335 {
1336         D3DPSREGISTER_Alpha = 0,
1337         D3DPSREGISTER_BloomBlur_Parameters = 1,
1338         D3DPSREGISTER_ClientTime = 2,
1339         D3DPSREGISTER_Color_Ambient = 3,
1340         D3DPSREGISTER_Color_Diffuse = 4,
1341         D3DPSREGISTER_Color_Specular = 5,
1342         D3DPSREGISTER_Color_Glow = 6,
1343         D3DPSREGISTER_Color_Pants = 7,
1344         D3DPSREGISTER_Color_Shirt = 8,
1345         D3DPSREGISTER_DeferredColor_Ambient = 9,
1346         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1347         D3DPSREGISTER_DeferredColor_Specular = 11,
1348         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1349         D3DPSREGISTER_DeferredMod_Specular = 13,
1350         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1351         D3DPSREGISTER_EyePosition = 15, // unused
1352         D3DPSREGISTER_FogColor = 16,
1353         D3DPSREGISTER_FogHeightFade = 17,
1354         D3DPSREGISTER_FogPlane = 18,
1355         D3DPSREGISTER_FogPlaneViewDist = 19,
1356         D3DPSREGISTER_FogRangeRecip = 20,
1357         D3DPSREGISTER_LightColor = 21,
1358         D3DPSREGISTER_LightDir = 22, // unused
1359         D3DPSREGISTER_LightPosition = 23,
1360         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1361         D3DPSREGISTER_PixelSize = 25,
1362         D3DPSREGISTER_ReflectColor = 26,
1363         D3DPSREGISTER_ReflectFactor = 27,
1364         D3DPSREGISTER_ReflectOffset = 28,
1365         D3DPSREGISTER_RefractColor = 29,
1366         D3DPSREGISTER_Saturation = 30,
1367         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1368         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1369         D3DPSREGISTER_ScreenToDepth = 33,
1370         D3DPSREGISTER_ShadowMap_Parameters = 34,
1371         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1372         D3DPSREGISTER_SpecularPower = 36,
1373         D3DPSREGISTER_UserVec1 = 37,
1374         D3DPSREGISTER_UserVec2 = 38,
1375         D3DPSREGISTER_UserVec3 = 39,
1376         D3DPSREGISTER_UserVec4 = 40,
1377         D3DPSREGISTER_ViewTintColor = 41,
1378         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1379         D3DPSREGISTER_BloomColorSubtract = 43,
1380         D3DPSREGISTER_ViewToLight = 44, // float4x4
1381         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1382         D3DPSREGISTER_NormalmapScrollBlend = 52,
1383         // next at 53
1384 }
1385 D3DPSREGISTER_t;
1386
1387 /// information about each possible shader permutation
1388 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1389 /// currently selected permutation
1390 r_hlsl_permutation_t *r_hlsl_permutation;
1391 /// storage for permutations linked in the hash table
1392 memexpandablearray_t r_hlsl_permutationarray;
1393
1394 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1395 {
1396         //unsigned int hashdepth = 0;
1397         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1398         r_hlsl_permutation_t *p;
1399         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1400         {
1401                 if (p->mode == mode && p->permutation == permutation)
1402                 {
1403                         //if (hashdepth > 10)
1404                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1405                         return p;
1406                 }
1407                 //hashdepth++;
1408         }
1409         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1410         p->mode = mode;
1411         p->permutation = permutation;
1412         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1413         r_hlsl_permutationhash[mode][hashindex] = p;
1414         //if (hashdepth > 10)
1415         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1416         return p;
1417 }
1418
1419 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1420 {
1421         char *shaderstring;
1422         if (!filename || !filename[0])
1423                 return NULL;
1424         if (!strcmp(filename, "hlsl/default.hlsl"))
1425         {
1426                 if (!hlslshaderstring)
1427                 {
1428                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1429                         if (hlslshaderstring)
1430                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1431                         else
1432                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1433                 }
1434                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1435                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1436                 return shaderstring;
1437         }
1438         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1439         if (shaderstring)
1440         {
1441                 if (printfromdisknotice)
1442                         Con_DPrintf("from disk %s... ", filename);
1443                 return shaderstring;
1444         }
1445         return shaderstring;
1446 }
1447
1448 #include <d3dx9.h>
1449 //#include <d3dx9shader.h>
1450 //#include <d3dx9mesh.h>
1451
1452 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1453 {
1454         DWORD *vsbin = NULL;
1455         DWORD *psbin = NULL;
1456         fs_offset_t vsbinsize;
1457         fs_offset_t psbinsize;
1458 //      IDirect3DVertexShader9 *vs = NULL;
1459 //      IDirect3DPixelShader9 *ps = NULL;
1460         ID3DXBuffer *vslog = NULL;
1461         ID3DXBuffer *vsbuffer = NULL;
1462         ID3DXConstantTable *vsconstanttable = NULL;
1463         ID3DXBuffer *pslog = NULL;
1464         ID3DXBuffer *psbuffer = NULL;
1465         ID3DXConstantTable *psconstanttable = NULL;
1466         int vsresult = 0;
1467         int psresult = 0;
1468         char temp[MAX_INPUTLINE];
1469         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1470         qboolean debugshader = gl_paranoid.integer != 0;
1471         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1472         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1473         if (!debugshader)
1474         {
1475                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1476                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1477         }
1478         if ((!vsbin && vertstring) || (!psbin && fragstring))
1479         {
1480                 const char* dllnames_d3dx9 [] =
1481                 {
1482                         "d3dx9_43.dll",
1483                         "d3dx9_42.dll",
1484                         "d3dx9_41.dll",
1485                         "d3dx9_40.dll",
1486                         "d3dx9_39.dll",
1487                         "d3dx9_38.dll",
1488                         "d3dx9_37.dll",
1489                         "d3dx9_36.dll",
1490                         "d3dx9_35.dll",
1491                         "d3dx9_34.dll",
1492                         "d3dx9_33.dll",
1493                         "d3dx9_32.dll",
1494                         "d3dx9_31.dll",
1495                         "d3dx9_30.dll",
1496                         "d3dx9_29.dll",
1497                         "d3dx9_28.dll",
1498                         "d3dx9_27.dll",
1499                         "d3dx9_26.dll",
1500                         "d3dx9_25.dll",
1501                         "d3dx9_24.dll",
1502                         NULL
1503                 };
1504                 dllhandle_t d3dx9_dll = NULL;
1505                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1506                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1507                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1508                 dllfunction_t d3dx9_dllfuncs[] =
1509                 {
1510                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1511                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1512                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1513                         {NULL, NULL}
1514                 };
1515                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1516                 {
1517                         DWORD shaderflags = 0;
1518                         if (debugshader)
1519                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1520                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1521                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1522                         if (vertstring && vertstring[0])
1523                         {
1524                                 if (debugshader)
1525                                 {
1526 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1527 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1528                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1529                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1530                                 }
1531                                 else
1532                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1533                                 if (vsbuffer)
1534                                 {
1535                                         vsbinsize = vsbuffer->GetBufferSize();
1536                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1537                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1538                                         vsbuffer->Release();
1539                                 }
1540                                 if (vslog)
1541                                 {
1542                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1543                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1544                                         vslog->Release();
1545                                 }
1546                         }
1547                         if (fragstring && fragstring[0])
1548                         {
1549                                 if (debugshader)
1550                                 {
1551 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1552 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1553                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1554                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1555                                 }
1556                                 else
1557                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1558                                 if (psbuffer)
1559                                 {
1560                                         psbinsize = psbuffer->GetBufferSize();
1561                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1562                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1563                                         psbuffer->Release();
1564                                 }
1565                                 if (pslog)
1566                                 {
1567                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1568                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1569                                         pslog->Release();
1570                                 }
1571                         }
1572                         Sys_UnloadLibrary(&d3dx9_dll);
1573                 }
1574                 else
1575                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1576         }
1577         if (vsbin && psbin)
1578         {
1579                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1580                 if (FAILED(vsresult))
1581                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1582                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1583                 if (FAILED(psresult))
1584                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1585         }
1586         // free the shader data
1587         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1588         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1589 }
1590
1591 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1592 {
1593         int i;
1594         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1595         int vertstring_length = 0;
1596         int geomstring_length = 0;
1597         int fragstring_length = 0;
1598         char *t;
1599         char *vertexstring, *geometrystring, *fragmentstring;
1600         char *vertstring, *geomstring, *fragstring;
1601         char permutationname[256];
1602         char cachename[256];
1603         int vertstrings_count = 0;
1604         int geomstrings_count = 0;
1605         int fragstrings_count = 0;
1606         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1607         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1608         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1609
1610         if (p->compiled)
1611                 return;
1612         p->compiled = true;
1613         p->vertexshader = NULL;
1614         p->pixelshader = NULL;
1615
1616         permutationname[0] = 0;
1617         cachename[0] = 0;
1618         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1619         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1620         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1621
1622         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1623         strlcat(cachename, "hlsl/", sizeof(cachename));
1624
1625         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1626         vertstrings_count = 0;
1627         geomstrings_count = 0;
1628         fragstrings_count = 0;
1629         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1630         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1631         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1632
1633         // the first pretext is which type of shader to compile as
1634         // (later these will all be bound together as a program object)
1635         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1636         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1637         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1638
1639         // the second pretext is the mode (for example a light source)
1640         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1641         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1642         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1643         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1644         strlcat(cachename, modeinfo->name, sizeof(cachename));
1645
1646         // now add all the permutation pretexts
1647         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1648         {
1649                 if (permutation & (1<<i))
1650                 {
1651                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1652                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1653                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1654                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1655                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1656                 }
1657                 else
1658                 {
1659                         // keep line numbers correct
1660                         vertstrings_list[vertstrings_count++] = "\n";
1661                         geomstrings_list[geomstrings_count++] = "\n";
1662                         fragstrings_list[fragstrings_count++] = "\n";
1663                 }
1664         }
1665
1666         // add static parms
1667         R_CompileShader_AddStaticParms(mode, permutation);
1668         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1669         vertstrings_count += shaderstaticparms_count;
1670         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1671         geomstrings_count += shaderstaticparms_count;
1672         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1673         fragstrings_count += shaderstaticparms_count;
1674
1675         // replace spaces in the cachename with _ characters
1676         for (i = 0;cachename[i];i++)
1677                 if (cachename[i] == ' ')
1678                         cachename[i] = '_';
1679
1680         // now append the shader text itself
1681         vertstrings_list[vertstrings_count++] = vertexstring;
1682         geomstrings_list[geomstrings_count++] = geometrystring;
1683         fragstrings_list[fragstrings_count++] = fragmentstring;
1684
1685         // if any sources were NULL, clear the respective list
1686         if (!vertexstring)
1687                 vertstrings_count = 0;
1688         if (!geometrystring)
1689                 geomstrings_count = 0;
1690         if (!fragmentstring)
1691                 fragstrings_count = 0;
1692
1693         vertstring_length = 0;
1694         for (i = 0;i < vertstrings_count;i++)
1695                 vertstring_length += strlen(vertstrings_list[i]);
1696         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1697         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1698                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1699
1700         geomstring_length = 0;
1701         for (i = 0;i < geomstrings_count;i++)
1702                 geomstring_length += strlen(geomstrings_list[i]);
1703         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1704         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1705                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1706
1707         fragstring_length = 0;
1708         for (i = 0;i < fragstrings_count;i++)
1709                 fragstring_length += strlen(fragstrings_list[i]);
1710         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1711         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1712                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1713
1714         // try to load the cached shader, or generate one
1715         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1716
1717         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1718                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1719         else
1720                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1721
1722         // free the strings
1723         if (vertstring)
1724                 Mem_Free(vertstring);
1725         if (geomstring)
1726                 Mem_Free(geomstring);
1727         if (fragstring)
1728                 Mem_Free(fragstring);
1729         if (vertexstring)
1730                 Mem_Free(vertexstring);
1731         if (geometrystring)
1732                 Mem_Free(geometrystring);
1733         if (fragmentstring)
1734                 Mem_Free(fragmentstring);
1735 }
1736
1737 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1738 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1739 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);}
1740 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);}
1741 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);}
1742 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);}
1743
1744 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1745 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1746 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);}
1747 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);}
1748 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);}
1749 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);}
1750
1751 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1752 {
1753         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1754         if (r_hlsl_permutation != perm)
1755         {
1756                 r_hlsl_permutation = perm;
1757                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1758                 {
1759                         if (!r_hlsl_permutation->compiled)
1760                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1761                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1762                         {
1763                                 // remove features until we find a valid permutation
1764                                 int i;
1765                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1766                                 {
1767                                         // reduce i more quickly whenever it would not remove any bits
1768                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1769                                         if (!(permutation & j))
1770                                                 continue;
1771                                         permutation -= j;
1772                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1773                                         if (!r_hlsl_permutation->compiled)
1774                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1775                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1776                                                 break;
1777                                 }
1778                                 if (i >= SHADERPERMUTATION_COUNT)
1779                                 {
1780                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1781                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1782                                         return; // no bit left to clear, entire mode is broken
1783                                 }
1784                         }
1785                 }
1786                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1787                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1788         }
1789         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1790         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1791         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1792 }
1793 #endif
1794
1795 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1796 {
1797         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1798         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1799         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1800         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1801 }
1802
1803 void R_GLSL_Restart_f(void)
1804 {
1805         unsigned int i, limit;
1806         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1807                 Mem_Free(glslshaderstring);
1808         glslshaderstring = NULL;
1809         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1810                 Mem_Free(hlslshaderstring);
1811         hlslshaderstring = NULL;
1812         switch(vid.renderpath)
1813         {
1814         case RENDERPATH_D3D9:
1815 #ifdef SUPPORTD3D
1816                 {
1817                         r_hlsl_permutation_t *p;
1818                         r_hlsl_permutation = NULL;
1819                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1820                         for (i = 0;i < limit;i++)
1821                         {
1822                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1823                                 {
1824                                         if (p->vertexshader)
1825                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1826                                         if (p->pixelshader)
1827                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1828                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1829                                 }
1830                         }
1831                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1832                 }
1833 #endif
1834                 break;
1835         case RENDERPATH_D3D10:
1836                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1837                 break;
1838         case RENDERPATH_D3D11:
1839                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1840                 break;
1841         case RENDERPATH_GL20:
1842         case RENDERPATH_GLES2:
1843                 {
1844                         r_glsl_permutation_t *p;
1845                         r_glsl_permutation = NULL;
1846                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1847                         for (i = 0;i < limit;i++)
1848                         {
1849                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1850                                 {
1851                                         GL_Backend_FreeProgram(p->program);
1852                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1853                                 }
1854                         }
1855                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1856                 }
1857                 break;
1858         case RENDERPATH_GL11:
1859         case RENDERPATH_GL13:
1860         case RENDERPATH_GLES1:
1861                 break;
1862         case RENDERPATH_SOFT:
1863                 break;
1864         }
1865 }
1866
1867 void R_GLSL_DumpShader_f(void)
1868 {
1869         int i;
1870         qfile_t *file;
1871
1872         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1873         if (file)
1874         {
1875                 FS_Print(file, "/* The engine may define the following macros:\n");
1876                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1877                 for (i = 0;i < SHADERMODE_COUNT;i++)
1878                         FS_Print(file, glslshadermodeinfo[i].pretext);
1879                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1880                         FS_Print(file, shaderpermutationinfo[i].pretext);
1881                 FS_Print(file, "*/\n");
1882                 FS_Print(file, builtinshaderstring);
1883                 FS_Close(file);
1884                 Con_Printf("glsl/default.glsl written\n");
1885         }
1886         else
1887                 Con_Printf("failed to write to glsl/default.glsl\n");
1888
1889         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1890         if (file)
1891         {
1892                 FS_Print(file, "/* The engine may define the following macros:\n");
1893                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1894                 for (i = 0;i < SHADERMODE_COUNT;i++)
1895                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1896                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1897                         FS_Print(file, shaderpermutationinfo[i].pretext);
1898                 FS_Print(file, "*/\n");
1899                 FS_Print(file, builtinhlslshaderstring);
1900                 FS_Close(file);
1901                 Con_Printf("hlsl/default.hlsl written\n");
1902         }
1903         else
1904                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1905 }
1906
1907 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1908 {
1909         if (!second)
1910                 texturemode = GL_MODULATE;
1911         switch (vid.renderpath)
1912         {
1913         case RENDERPATH_D3D9:
1914 #ifdef SUPPORTD3D
1915                 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))));
1916                 R_Mesh_TexBind(GL20TU_FIRST , first );
1917                 R_Mesh_TexBind(GL20TU_SECOND, second);
1918 #endif
1919                 break;
1920         case RENDERPATH_D3D10:
1921                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1922                 break;
1923         case RENDERPATH_D3D11:
1924                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1925                 break;
1926         case RENDERPATH_GL20:
1927         case RENDERPATH_GLES2:
1928                 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))));
1929                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1930                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1931                 break;
1932         case RENDERPATH_GL13:
1933         case RENDERPATH_GLES1:
1934                 R_Mesh_TexBind(0, first );
1935                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1936                 R_Mesh_TexBind(1, second);
1937                 if (second)
1938                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1939                 break;
1940         case RENDERPATH_GL11:
1941                 R_Mesh_TexBind(0, first );
1942                 break;
1943         case RENDERPATH_SOFT:
1944                 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))));
1945                 R_Mesh_TexBind(GL20TU_FIRST , first );
1946                 R_Mesh_TexBind(GL20TU_SECOND, second);
1947                 break;
1948         }
1949 }
1950
1951 void R_SetupShader_DepthOrShadow(void)
1952 {
1953         switch (vid.renderpath)
1954         {
1955         case RENDERPATH_D3D9:
1956 #ifdef SUPPORTD3D
1957                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1958 #endif
1959                 break;
1960         case RENDERPATH_D3D10:
1961                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1962                 break;
1963         case RENDERPATH_D3D11:
1964                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1965                 break;
1966         case RENDERPATH_GL20:
1967         case RENDERPATH_GLES2:
1968                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1969                 break;
1970         case RENDERPATH_GL13:
1971         case RENDERPATH_GLES1:
1972                 R_Mesh_TexBind(0, 0);
1973                 R_Mesh_TexBind(1, 0);
1974                 break;
1975         case RENDERPATH_GL11:
1976                 R_Mesh_TexBind(0, 0);
1977                 break;
1978         case RENDERPATH_SOFT:
1979                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1980                 break;
1981         }
1982 }
1983
1984 void R_SetupShader_ShowDepth(void)
1985 {
1986         switch (vid.renderpath)
1987         {
1988         case RENDERPATH_D3D9:
1989 #ifdef SUPPORTHLSL
1990                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1991 #endif
1992                 break;
1993         case RENDERPATH_D3D10:
1994                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1995                 break;
1996         case RENDERPATH_D3D11:
1997                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1998                 break;
1999         case RENDERPATH_GL20:
2000         case RENDERPATH_GLES2:
2001                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
2002                 break;
2003         case RENDERPATH_GL13:
2004         case RENDERPATH_GLES1:
2005                 break;
2006         case RENDERPATH_GL11:
2007                 break;
2008         case RENDERPATH_SOFT:
2009                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2010                 break;
2011         }
2012 }
2013
2014 extern qboolean r_shadow_usingdeferredprepass;
2015 extern cvar_t r_shadow_deferred_8bitrange;
2016 extern rtexture_t *r_shadow_attenuationgradienttexture;
2017 extern rtexture_t *r_shadow_attenuation2dtexture;
2018 extern rtexture_t *r_shadow_attenuation3dtexture;
2019 extern qboolean r_shadow_usingshadowmap2d;
2020 extern qboolean r_shadow_usingshadowmaportho;
2021 extern float r_shadow_shadowmap_texturescale[2];
2022 extern float r_shadow_shadowmap_parameters[4];
2023 extern qboolean r_shadow_shadowmapvsdct;
2024 extern qboolean r_shadow_shadowmapsampler;
2025 extern int r_shadow_shadowmappcf;
2026 extern rtexture_t *r_shadow_shadowmap2dtexture;
2027 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2028 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2029 extern matrix4x4_t r_shadow_shadowmapmatrix;
2030 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2031 extern int r_shadow_prepass_width;
2032 extern int r_shadow_prepass_height;
2033 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2034 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2035 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2036 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2037 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2038
2039 #define BLENDFUNC_ALLOWS_COLORMOD      1
2040 #define BLENDFUNC_ALLOWS_FOG           2
2041 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2042 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2043 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2044 static int R_BlendFuncFlags(int src, int dst)
2045 {
2046         int r = 0;
2047
2048         // a blendfunc allows colormod if:
2049         // a) it can never keep the destination pixel invariant, or
2050         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2051         // this is to prevent unintended side effects from colormod
2052
2053         // a blendfunc allows fog if:
2054         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2055         // this is to prevent unintended side effects from fog
2056
2057         // these checks are the output of fogeval.pl
2058
2059         r |= BLENDFUNC_ALLOWS_COLORMOD;
2060         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2061         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2062         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2063         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2064         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2065         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2066         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2067         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2068         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2069         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2070         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2071         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2072         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2073         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2074         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2075         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2076         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2077         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2078         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2079         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2080         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2081
2082         return r;
2083 }
2084
2085 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)
2086 {
2087         // select a permutation of the lighting shader appropriate to this
2088         // combination of texture, entity, light source, and fogging, only use the
2089         // minimum features necessary to avoid wasting rendering time in the
2090         // fragment shader on features that are not being used
2091         unsigned int permutation = 0;
2092         unsigned int mode = 0;
2093         int blendfuncflags;
2094         static float dummy_colormod[3] = {1, 1, 1};
2095         float *colormod = rsurface.colormod;
2096         float m16f[16];
2097         matrix4x4_t tempmatrix;
2098         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2099         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2100                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2101         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2102                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2103         if (rsurfacepass == RSURFPASS_BACKGROUND)
2104         {
2105                 // distorted background
2106                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2107                 {
2108                         mode = SHADERMODE_WATER;
2109                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2110                         {
2111                                 // this is the right thing to do for wateralpha
2112                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2113                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2114                         }
2115                         else
2116                         {
2117                                 // this is the right thing to do for entity alpha
2118                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2119                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2120                         }
2121                 }
2122                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2123                 {
2124                         mode = SHADERMODE_REFRACTION;
2125                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2126                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2127                 }
2128                 else
2129                 {
2130                         mode = SHADERMODE_GENERIC;
2131                         permutation |= SHADERPERMUTATION_DIFFUSE;
2132                         GL_BlendFunc(GL_ONE, GL_ZERO);
2133                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2134                 }
2135         }
2136         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2137         {
2138                 if (r_glsl_offsetmapping.integer)
2139                 {
2140                         switch(rsurface.texture->offsetmapping)
2141                         {
2142                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2143                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2144                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2145                         case OFFSETMAPPING_OFF: break;
2146                         }
2147                 }
2148                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2149                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2150                 // normalmap (deferred prepass), may use alpha test on diffuse
2151                 mode = SHADERMODE_DEFERREDGEOMETRY;
2152                 GL_BlendFunc(GL_ONE, GL_ZERO);
2153                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2154         }
2155         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2156         {
2157                 if (r_glsl_offsetmapping.integer)
2158                 {
2159                         switch(rsurface.texture->offsetmapping)
2160                         {
2161                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2162                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2163                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2164                         case OFFSETMAPPING_OFF: break;
2165                         }
2166                 }
2167                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2168                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2169                 // light source
2170                 mode = SHADERMODE_LIGHTSOURCE;
2171                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2172                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2173                 if (diffusescale > 0)
2174                         permutation |= SHADERPERMUTATION_DIFFUSE;
2175                 if (specularscale > 0)
2176                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2177                 if (r_refdef.fogenabled)
2178                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2179                 if (rsurface.texture->colormapping)
2180                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2181                 if (r_shadow_usingshadowmap2d)
2182                 {
2183                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2184                         if(r_shadow_shadowmapvsdct)
2185                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2186
2187                         if (r_shadow_shadowmapsampler)
2188                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2189                         if (r_shadow_shadowmappcf > 1)
2190                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2191                         else if (r_shadow_shadowmappcf)
2192                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2193                 }
2194                 if (rsurface.texture->reflectmasktexture)
2195                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2196                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2197                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2198         }
2199         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2200         {
2201                 if (r_glsl_offsetmapping.integer)
2202                 {
2203                         switch(rsurface.texture->offsetmapping)
2204                         {
2205                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2206                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2207                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2208                         case OFFSETMAPPING_OFF: break;
2209                         }
2210                 }
2211                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2212                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2213                 // unshaded geometry (fullbright or ambient model lighting)
2214                 mode = SHADERMODE_FLATCOLOR;
2215                 ambientscale = diffusescale = specularscale = 0;
2216                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2217                         permutation |= SHADERPERMUTATION_GLOW;
2218                 if (r_refdef.fogenabled)
2219                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2220                 if (rsurface.texture->colormapping)
2221                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2222                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2223                 {
2224                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2225                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2226
2227                         if (r_shadow_shadowmapsampler)
2228                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2229                         if (r_shadow_shadowmappcf > 1)
2230                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2231                         else if (r_shadow_shadowmappcf)
2232                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2233                 }
2234                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2235                         permutation |= SHADERPERMUTATION_REFLECTION;
2236                 if (rsurface.texture->reflectmasktexture)
2237                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2238                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2239                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2240         }
2241         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2242         {
2243                 if (r_glsl_offsetmapping.integer)
2244                 {
2245                         switch(rsurface.texture->offsetmapping)
2246                         {
2247                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2248                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2249                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2250                         case OFFSETMAPPING_OFF: break;
2251                         }
2252                 }
2253                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2254                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2255                 // directional model lighting
2256                 mode = SHADERMODE_LIGHTDIRECTION;
2257                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2258                         permutation |= SHADERPERMUTATION_GLOW;
2259                 permutation |= SHADERPERMUTATION_DIFFUSE;
2260                 if (specularscale > 0)
2261                         permutation |= SHADERPERMUTATION_SPECULAR;
2262                 if (r_refdef.fogenabled)
2263                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2264                 if (rsurface.texture->colormapping)
2265                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2266                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2267                 {
2268                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2269                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2270
2271                         if (r_shadow_shadowmapsampler)
2272                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2273                         if (r_shadow_shadowmappcf > 1)
2274                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2275                         else if (r_shadow_shadowmappcf)
2276                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2277                 }
2278                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2279                         permutation |= SHADERPERMUTATION_REFLECTION;
2280                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2281                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2282                 if (rsurface.texture->reflectmasktexture)
2283                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2284                 if (r_shadow_bouncegridtexture)
2285                 {
2286                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2287                         if (r_shadow_bouncegriddirectional)
2288                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2289                 }
2290                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2291                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2292         }
2293         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2294         {
2295                 if (r_glsl_offsetmapping.integer)
2296                 {
2297                         switch(rsurface.texture->offsetmapping)
2298                         {
2299                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2300                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2301                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2302                         case OFFSETMAPPING_OFF: break;
2303                         }
2304                 }
2305                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2306                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2307                 // ambient model lighting
2308                 mode = SHADERMODE_LIGHTDIRECTION;
2309                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2310                         permutation |= SHADERPERMUTATION_GLOW;
2311                 if (r_refdef.fogenabled)
2312                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2313                 if (rsurface.texture->colormapping)
2314                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2315                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2316                 {
2317                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2318                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2319
2320                         if (r_shadow_shadowmapsampler)
2321                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2322                         if (r_shadow_shadowmappcf > 1)
2323                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2324                         else if (r_shadow_shadowmappcf)
2325                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2326                 }
2327                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2328                         permutation |= SHADERPERMUTATION_REFLECTION;
2329                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2330                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2331                 if (rsurface.texture->reflectmasktexture)
2332                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2333                 if (r_shadow_bouncegridtexture)
2334                 {
2335                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2336                         if (r_shadow_bouncegriddirectional)
2337                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2338                 }
2339                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2340                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2341         }
2342         else
2343         {
2344                 if (r_glsl_offsetmapping.integer)
2345                 {
2346                         switch(rsurface.texture->offsetmapping)
2347                         {
2348                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2349                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2350                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2351                         case OFFSETMAPPING_OFF: break;
2352                         }
2353                 }
2354                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2355                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2356                 // lightmapped wall
2357                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2358                         permutation |= SHADERPERMUTATION_GLOW;
2359                 if (r_refdef.fogenabled)
2360                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2361                 if (rsurface.texture->colormapping)
2362                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2363                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2364                 {
2365                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2366                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2367
2368                         if (r_shadow_shadowmapsampler)
2369                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2370                         if (r_shadow_shadowmappcf > 1)
2371                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2372                         else if (r_shadow_shadowmappcf)
2373                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2374                 }
2375                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376                         permutation |= SHADERPERMUTATION_REFLECTION;
2377                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2378                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2379                 if (rsurface.texture->reflectmasktexture)
2380                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2381                 if (FAKELIGHT_ENABLED)
2382                 {
2383                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2384                         mode = SHADERMODE_FAKELIGHT;
2385                         permutation |= SHADERPERMUTATION_DIFFUSE;
2386                         if (specularscale > 0)
2387                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2388                 }
2389                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2390                 {
2391                         // deluxemapping (light direction texture)
2392                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2393                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2394                         else
2395                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2396                         permutation |= SHADERPERMUTATION_DIFFUSE;
2397                         if (specularscale > 0)
2398                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2399                 }
2400                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2401                 {
2402                         // fake deluxemapping (uniform light direction in tangentspace)
2403                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2404                         permutation |= SHADERPERMUTATION_DIFFUSE;
2405                         if (specularscale > 0)
2406                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2407                 }
2408                 else if (rsurface.uselightmaptexture)
2409                 {
2410                         // ordinary lightmapping (q1bsp, q3bsp)
2411                         mode = SHADERMODE_LIGHTMAP;
2412                 }
2413                 else
2414                 {
2415                         // ordinary vertex coloring (q3bsp)
2416                         mode = SHADERMODE_VERTEXCOLOR;
2417                 }
2418                 if (r_shadow_bouncegridtexture)
2419                 {
2420                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2421                         if (r_shadow_bouncegriddirectional)
2422                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2423                 }
2424                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2425                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2426         }
2427         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2428                 colormod = dummy_colormod;
2429         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2430                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2431         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2432                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2433         switch(vid.renderpath)
2434         {
2435         case RENDERPATH_D3D9:
2436 #ifdef SUPPORTD3D
2437                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2438                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2439                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2440                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2441                 if (mode == SHADERMODE_LIGHTSOURCE)
2442                 {
2443                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2444                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2445                 }
2446                 else
2447                 {
2448                         if (mode == SHADERMODE_LIGHTDIRECTION)
2449                         {
2450                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2451                         }
2452                 }
2453                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2454                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2455                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2456                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2457                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2458
2459                 if (mode == SHADERMODE_LIGHTSOURCE)
2460                 {
2461                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2462                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2463                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2464                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2465                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2466
2467                         // additive passes are only darkened by fog, not tinted
2468                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2469                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2470                 }
2471                 else
2472                 {
2473                         if (mode == SHADERMODE_FLATCOLOR)
2474                         {
2475                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2476                         }
2477                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2478                         {
2479                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2480                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2481                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2482                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2483                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2484                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2485                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2486                         }
2487                         else
2488                         {
2489                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2490                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2491                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2492                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2493                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2494                         }
2495                         // additive passes are only darkened by fog, not tinted
2496                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2497                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2498                         else
2499                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2500                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2501                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2502                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2503                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2504                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2505                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2506                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2507                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2508                         if (mode == SHADERMODE_WATER)
2509                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2510                 }
2511                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2512                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2513                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2514                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2515                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2516                 if (rsurface.texture->pantstexture)
2517                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2518                 else
2519                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2520                 if (rsurface.texture->shirttexture)
2521                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2522                 else
2523                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2524                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2525                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2526                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2527                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2528                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2529                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2530                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2531                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2532                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2533                         );
2534                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2535                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2536
2537                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2538                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2539                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2540                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2541                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2542                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2543                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2544                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2545                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2546                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2547                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2548                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2549                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2550                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2551                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2552                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2553                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2554                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2555                 {
2556                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2557                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2558                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2559                 }
2560                 else
2561                 {
2562                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2563                 }
2564 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2565 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2566                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2567                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2568                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2569                 {
2570                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2571                         if (rsurface.rtlight)
2572                         {
2573                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2574                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2575                         }
2576                 }
2577 #endif
2578                 break;
2579         case RENDERPATH_D3D10:
2580                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2581                 break;
2582         case RENDERPATH_D3D11:
2583                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2584                 break;
2585         case RENDERPATH_GL20:
2586         case RENDERPATH_GLES2:
2587                 if (!vid.useinterleavedarrays)
2588                 {
2589                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2590                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2591                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2592                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2593                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2594                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2595                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2596                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2597                 }
2598                 else
2599                 {
2600                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2601                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2602                 }
2603                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2604                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2605                 if (mode == SHADERMODE_LIGHTSOURCE)
2606                 {
2607                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2608                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2609                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2610                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2611                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2612                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2613         
2614                         // additive passes are only darkened by fog, not tinted
2615                         if (r_glsl_permutation->loc_FogColor >= 0)
2616                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2617                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2618                 }
2619                 else
2620                 {
2621                         if (mode == SHADERMODE_FLATCOLOR)
2622                         {
2623                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2624                         }
2625                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2626                         {
2627                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2628                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2629                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2630                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2631                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2632                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2633                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2634                         }
2635                         else
2636                         {
2637                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2638                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2639                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2640                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2641                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2642                         }
2643                         // additive passes are only darkened by fog, not tinted
2644                         if (r_glsl_permutation->loc_FogColor >= 0)
2645                         {
2646                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2647                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2648                                 else
2649                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2650                         }
2651                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2652                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2653                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2654                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2655                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2656                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2657                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2658                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2659                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2660                 }
2661                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2662                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2663                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2664                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2665                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2666
2667                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2668                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2669                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2670                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2671                 {
2672                         if (rsurface.texture->pantstexture)
2673                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2674                         else
2675                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2676                 }
2677                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2678                 {
2679                         if (rsurface.texture->shirttexture)
2680                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2681                         else
2682                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2683                 }
2684                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2685                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2686                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2687                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2688                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2689                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2690                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2691                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2692                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2693                         );
2694                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2695                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2696                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2697                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2698
2699                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2700                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2701                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2702                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2703                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2704                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2705                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2706                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2707                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2708                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2709                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2710                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2711                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2712                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2713                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2714                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2715                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2716                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2717                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2718                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2719                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2720                 {
2721                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2722                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2723                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2724                 }
2725                 else
2726                 {
2727                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2728                 }
2729                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2730                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2731                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2732                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2733                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2734                 {
2735                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2736                         if (rsurface.rtlight)
2737                         {
2738                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2739                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2740                         }
2741                 }
2742                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2743                 CHECKGLERROR
2744                 break;
2745         case RENDERPATH_GL11:
2746         case RENDERPATH_GL13:
2747         case RENDERPATH_GLES1:
2748                 break;
2749         case RENDERPATH_SOFT:
2750                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2751                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2752                 R_SetupShader_SetPermutationSoft(mode, permutation);
2753                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2754                 if (mode == SHADERMODE_LIGHTSOURCE)
2755                 {
2756                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2757                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2758                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2759                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2760                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2761                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2762         
2763                         // additive passes are only darkened by fog, not tinted
2764                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2765                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2766                 }
2767                 else
2768                 {
2769                         if (mode == SHADERMODE_FLATCOLOR)
2770                         {
2771                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2772                         }
2773                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2774                         {
2775                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2776                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2777                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2778                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2779                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2780                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2781                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2782                         }
2783                         else
2784                         {
2785                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2786                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2787                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2788                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2789                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2790                         }
2791                         // additive passes are only darkened by fog, not tinted
2792                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2793                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2794                         else
2795                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2796                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2797                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2798                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2799                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2800                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2801                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2802                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2803                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2804                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2805                 }
2806                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2807                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2808                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2809                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2810                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2811
2812                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2813                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2814                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2815                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2816                 {
2817                         if (rsurface.texture->pantstexture)
2818                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2819                         else
2820                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2821                 }
2822                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2823                 {
2824                         if (rsurface.texture->shirttexture)
2825                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2826                         else
2827                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2828                 }
2829                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2830                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2831                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2832                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2833                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2834                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2835                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2836                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2837                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2838                         );
2839                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2840                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2841
2842                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2843                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2844                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2845                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2846                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2847                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2848                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2849                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2850                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2851                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2852                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2853                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2854                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2855                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2856                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2857                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2858                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2859                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2860                 {
2861                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2862                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2863                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2864                 }
2865                 else
2866                 {
2867                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2868                 }
2869 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2870 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2871                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2872                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2873                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2874                 {
2875                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2876                         if (rsurface.rtlight)
2877                         {
2878                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2879                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2880                         }
2881                 }
2882                 break;
2883         }
2884 }
2885
2886 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2887 {
2888         // select a permutation of the lighting shader appropriate to this
2889         // combination of texture, entity, light source, and fogging, only use the
2890         // minimum features necessary to avoid wasting rendering time in the
2891         // fragment shader on features that are not being used
2892         unsigned int permutation = 0;
2893         unsigned int mode = 0;
2894         const float *lightcolorbase = rtlight->currentcolor;
2895         float ambientscale = rtlight->ambientscale;
2896         float diffusescale = rtlight->diffusescale;
2897         float specularscale = rtlight->specularscale;
2898         // this is the location of the light in view space
2899         vec3_t viewlightorigin;
2900         // this transforms from view space (camera) to light space (cubemap)
2901         matrix4x4_t viewtolight;
2902         matrix4x4_t lighttoview;
2903         float viewtolight16f[16];
2904         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2905         // light source
2906         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2907         if (rtlight->currentcubemap != r_texture_whitecube)
2908                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2909         if (diffusescale > 0)
2910                 permutation |= SHADERPERMUTATION_DIFFUSE;
2911         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2912                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2913         if (r_shadow_usingshadowmap2d)
2914         {
2915                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2916                 if (r_shadow_shadowmapvsdct)
2917                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2918
2919                 if (r_shadow_shadowmapsampler)
2920                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2921                 if (r_shadow_shadowmappcf > 1)
2922                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2923                 else if (r_shadow_shadowmappcf)
2924                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2925         }
2926         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2927         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2928         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2929         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2930         switch(vid.renderpath)
2931         {
2932         case RENDERPATH_D3D9:
2933 #ifdef SUPPORTD3D
2934                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2935                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2936                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2937                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2938                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2939                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2940                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2941                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2942                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2943                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2944                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2945
2946                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2947                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2948                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2949                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2950                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2951                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2952 #endif
2953                 break;
2954         case RENDERPATH_D3D10:
2955                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2956                 break;
2957         case RENDERPATH_D3D11:
2958                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2959                 break;
2960         case RENDERPATH_GL20:
2961         case RENDERPATH_GLES2:
2962                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2963                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2964                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2965                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2966                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2967                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2968                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2969                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2970                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2971                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2972                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2973
2974                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2975                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2976                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2977                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2978                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2979                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2980                 break;
2981         case RENDERPATH_GL11:
2982         case RENDERPATH_GL13:
2983         case RENDERPATH_GLES1:
2984                 break;
2985         case RENDERPATH_SOFT:
2986                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2987                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2988                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2989                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2990                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2991                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2992                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2993                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2994                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2995                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2996                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2997
2998                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2999                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3000                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3001                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3002                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3003                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3004                 break;
3005         }
3006 }
3007
3008 #define SKINFRAME_HASH 1024
3009
3010 typedef struct
3011 {
3012         int loadsequence; // incremented each level change
3013         memexpandablearray_t array;
3014         skinframe_t *hash[SKINFRAME_HASH];
3015 }
3016 r_skinframe_t;
3017 r_skinframe_t r_skinframe;
3018
3019 void R_SkinFrame_PrepareForPurge(void)
3020 {
3021         r_skinframe.loadsequence++;
3022         // wrap it without hitting zero
3023         if (r_skinframe.loadsequence >= 200)
3024                 r_skinframe.loadsequence = 1;
3025 }
3026
3027 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3028 {
3029         if (!skinframe)
3030                 return;
3031         // mark the skinframe as used for the purging code
3032         skinframe->loadsequence = r_skinframe.loadsequence;
3033 }
3034
3035 void R_SkinFrame_Purge(void)
3036 {
3037         int i;
3038         skinframe_t *s;
3039         for (i = 0;i < SKINFRAME_HASH;i++)
3040         {
3041                 for (s = r_skinframe.hash[i];s;s = s->next)
3042                 {
3043                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3044                         {
3045                                 if (s->merged == s->base)
3046                                         s->merged = NULL;
3047                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3048                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3049                                 R_PurgeTexture(s->merged);s->merged = NULL;
3050                                 R_PurgeTexture(s->base  );s->base   = NULL;
3051                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3052                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3053                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3054                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3055                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3056                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3057                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3058                                 s->loadsequence = 0;
3059                         }
3060                 }
3061         }
3062 }
3063
3064 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3065         skinframe_t *item;
3066         char basename[MAX_QPATH];
3067
3068         Image_StripImageExtension(name, basename, sizeof(basename));
3069
3070         if( last == NULL ) {
3071                 int hashindex;
3072                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3073                 item = r_skinframe.hash[hashindex];
3074         } else {
3075                 item = last->next;
3076         }
3077
3078         // linearly search through the hash bucket
3079         for( ; item ; item = item->next ) {
3080                 if( !strcmp( item->basename, basename ) ) {
3081                         return item;
3082                 }
3083         }
3084         return NULL;
3085 }
3086
3087 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3088 {
3089         skinframe_t *item;
3090         int hashindex;
3091         char basename[MAX_QPATH];
3092
3093         Image_StripImageExtension(name, basename, sizeof(basename));
3094
3095         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3096         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3097                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3098                         break;
3099
3100         if (!item) {
3101                 rtexture_t *dyntexture;
3102                 // check whether its a dynamic texture
3103                 dyntexture = CL_GetDynTexture( basename );
3104                 if (!add && !dyntexture)
3105                         return NULL;
3106                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3107                 memset(item, 0, sizeof(*item));
3108                 strlcpy(item->basename, basename, sizeof(item->basename));
3109                 item->base = dyntexture; // either NULL or dyntexture handle
3110                 item->textureflags = textureflags;
3111                 item->comparewidth = comparewidth;
3112                 item->compareheight = compareheight;
3113                 item->comparecrc = comparecrc;
3114                 item->next = r_skinframe.hash[hashindex];
3115                 r_skinframe.hash[hashindex] = item;
3116         }
3117         else if( item->base == NULL )
3118         {
3119                 rtexture_t *dyntexture;
3120                 // check whether its a dynamic texture
3121                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3122                 dyntexture = CL_GetDynTexture( basename );
3123                 item->base = dyntexture; // either NULL or dyntexture handle
3124         }
3125
3126         R_SkinFrame_MarkUsed(item);
3127         return item;
3128 }
3129
3130 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3131         { \
3132                 unsigned long long avgcolor[5], wsum; \
3133                 int pix, comp, w; \
3134                 avgcolor[0] = 0; \
3135                 avgcolor[1] = 0; \
3136                 avgcolor[2] = 0; \
3137                 avgcolor[3] = 0; \
3138                 avgcolor[4] = 0; \
3139                 wsum = 0; \
3140                 for(pix = 0; pix < cnt; ++pix) \
3141                 { \
3142                         w = 0; \
3143                         for(comp = 0; comp < 3; ++comp) \
3144                                 w += getpixel; \
3145                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3146                         { \
3147                                 ++wsum; \
3148                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3149                                 w = getpixel; \
3150                                 for(comp = 0; comp < 3; ++comp) \
3151                                         avgcolor[comp] += getpixel * w; \
3152                                 avgcolor[3] += w; \
3153                         } \
3154                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3155                         avgcolor[4] += getpixel; \
3156                 } \
3157                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3158                         avgcolor[3] = 1; \
3159                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3160                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3161                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3162                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3163         }
3164
3165 extern cvar_t gl_picmip;
3166 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3167 {
3168         int j;
3169         unsigned char *pixels;
3170         unsigned char *bumppixels;
3171         unsigned char *basepixels = NULL;
3172         int basepixels_width = 0;
3173         int basepixels_height = 0;
3174         skinframe_t *skinframe;
3175         rtexture_t *ddsbase = NULL;
3176         qboolean ddshasalpha = false;
3177         float ddsavgcolor[4];
3178         char basename[MAX_QPATH];
3179         int miplevel = R_PicmipForFlags(textureflags);
3180         int savemiplevel = miplevel;
3181         int mymiplevel;
3182
3183         if (cls.state == ca_dedicated)
3184                 return NULL;
3185
3186         // return an existing skinframe if already loaded
3187         // if loading of the first image fails, don't make a new skinframe as it
3188         // would cause all future lookups of this to be missing
3189         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3190         if (skinframe && skinframe->base)
3191                 return skinframe;
3192
3193         Image_StripImageExtension(name, basename, sizeof(basename));
3194
3195         // check for DDS texture file first
3196         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3197         {
3198                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3199                 if (basepixels == NULL)
3200                         return NULL;
3201         }
3202
3203         // FIXME handle miplevel
3204
3205         if (developer_loading.integer)
3206                 Con_Printf("loading skin \"%s\"\n", name);
3207
3208         // we've got some pixels to store, so really allocate this new texture now
3209         if (!skinframe)
3210                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3211         skinframe->stain = NULL;
3212         skinframe->merged = NULL;
3213         skinframe->base = NULL;
3214         skinframe->pants = NULL;
3215         skinframe->shirt = NULL;
3216         skinframe->nmap = NULL;
3217         skinframe->gloss = NULL;
3218         skinframe->glow = NULL;
3219         skinframe->fog = NULL;
3220         skinframe->reflect = NULL;
3221         skinframe->hasalpha = false;
3222
3223         if (ddsbase)
3224         {
3225                 skinframe->base = ddsbase;
3226                 skinframe->hasalpha = ddshasalpha;
3227                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3228                 if (r_loadfog && skinframe->hasalpha)
3229                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3230                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3231         }
3232         else
3233         {
3234                 basepixels_width = image_width;
3235                 basepixels_height = image_height;
3236                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3237                 if (textureflags & TEXF_ALPHA)
3238                 {
3239                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3240                         {
3241                                 if (basepixels[j] < 255)
3242                                 {
3243                                         skinframe->hasalpha = true;
3244                                         break;
3245                                 }
3246                         }
3247                         if (r_loadfog && skinframe->hasalpha)
3248                         {
3249                                 // has transparent pixels
3250                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3251                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3252                                 {
3253                                         pixels[j+0] = 255;
3254                                         pixels[j+1] = 255;
3255                                         pixels[j+2] = 255;
3256                                         pixels[j+3] = basepixels[j+3];
3257                                 }
3258                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3259                                 Mem_Free(pixels);
3260                         }
3261                 }
3262                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3263                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3264                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3265                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3266                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3267                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3268         }
3269
3270         if (r_loaddds)
3271         {
3272                 mymiplevel = savemiplevel;
3273                 if (r_loadnormalmap)
3274                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3275                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3276                 if (r_loadgloss)
3277                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3278                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3279                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3280                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3281         }
3282
3283         // _norm is the name used by tenebrae and has been adopted as standard
3284         if (r_loadnormalmap && skinframe->nmap == NULL)
3285         {
3286                 mymiplevel = savemiplevel;
3287                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3288                 {
3289                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3290                         Mem_Free(pixels);
3291                         pixels = NULL;
3292                 }
3293                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3294                 {
3295                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3296                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3297                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3298                         Mem_Free(pixels);
3299                         Mem_Free(bumppixels);
3300                 }
3301                 else if (r_shadow_bumpscale_basetexture.value > 0)
3302                 {
3303                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3304                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3305                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3306                         Mem_Free(pixels);
3307                 }
3308                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3309                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3310         }
3311
3312         // _luma is supported only for tenebrae compatibility
3313         // _glow is the preferred name
3314         mymiplevel = savemiplevel;
3315         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3316         {
3317                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_glow.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3318                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3319                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3320                 Mem_Free(pixels);pixels = NULL;
3321         }
3322
3323         mymiplevel = savemiplevel;
3324         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3325         {
3326                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_gloss.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3327                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3328                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3329                 Mem_Free(pixels);
3330                 pixels = NULL;
3331         }
3332
3333         mymiplevel = savemiplevel;
3334         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3335         {
3336                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3337                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3338                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3339                 Mem_Free(pixels);
3340                 pixels = NULL;
3341         }
3342
3343         mymiplevel = savemiplevel;
3344         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3345         {
3346                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3347                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3348                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3349                 Mem_Free(pixels);
3350                 pixels = NULL;
3351         }
3352
3353         mymiplevel = savemiplevel;
3354         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3355         {
3356                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_reflect.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3357                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3358                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3359                 Mem_Free(pixels);
3360                 pixels = NULL;
3361         }
3362
3363         if (basepixels)
3364                 Mem_Free(basepixels);
3365
3366         return skinframe;
3367 }
3368
3369 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3370 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3371 {
3372         int i;
3373         unsigned char *temp1, *temp2;
3374         skinframe_t *skinframe;
3375
3376         if (cls.state == ca_dedicated)
3377                 return NULL;
3378
3379         // if already loaded just return it, otherwise make a new skinframe
3380         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3381         if (skinframe && skinframe->base)
3382                 return skinframe;
3383
3384         skinframe->stain = NULL;
3385         skinframe->merged = NULL;
3386         skinframe->base = NULL;
3387         skinframe->pants = NULL;
3388         skinframe->shirt = NULL;
3389         skinframe->nmap = NULL;
3390         skinframe->gloss = NULL;
3391         skinframe->glow = NULL;
3392         skinframe->fog = NULL;
3393         skinframe->reflect = NULL;
3394         skinframe->hasalpha = false;
3395
3396         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3397         if (!skindata)
3398                 return NULL;
3399
3400         if (developer_loading.integer)
3401                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3402
3403         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3404         {
3405                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3406                 temp2 = temp1 + width * height * 4;
3407                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3408                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3409                 Mem_Free(temp1);
3410         }
3411         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3412         if (textureflags & TEXF_ALPHA)
3413         {
3414                 for (i = 3;i < width * height * 4;i += 4)
3415                 {
3416                         if (skindata[i] < 255)
3417                         {
3418                                 skinframe->hasalpha = true;
3419                                 break;
3420                         }
3421                 }
3422                 if (r_loadfog && skinframe->hasalpha)
3423                 {
3424                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3425                         memcpy(fogpixels, skindata, width * height * 4);
3426                         for (i = 0;i < width * height * 4;i += 4)
3427                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3428                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3429                         Mem_Free(fogpixels);
3430                 }
3431         }
3432
3433         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3434         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3435
3436         return skinframe;
3437 }
3438
3439 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3440 {
3441         int i;
3442         int featuresmask;
3443         skinframe_t *skinframe;
3444
3445         if (cls.state == ca_dedicated)
3446                 return NULL;
3447
3448         // if already loaded just return it, otherwise make a new skinframe
3449         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3450         if (skinframe && skinframe->base)
3451                 return skinframe;
3452
3453         skinframe->stain = NULL;
3454         skinframe->merged = NULL;
3455         skinframe->base = NULL;
3456         skinframe->pants = NULL;
3457         skinframe->shirt = NULL;
3458         skinframe->nmap = NULL;
3459         skinframe->gloss = NULL;
3460         skinframe->glow = NULL;
3461         skinframe->fog = NULL;
3462         skinframe->reflect = NULL;
3463         skinframe->hasalpha = false;
3464
3465         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3466         if (!skindata)
3467                 return NULL;
3468
3469         if (developer_loading.integer)
3470                 Con_Printf("loading quake skin \"%s\"\n", name);
3471
3472         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3473         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3474         memcpy(skinframe->qpixels, skindata, width*height);
3475         skinframe->qwidth = width;
3476         skinframe->qheight = height;
3477
3478         featuresmask = 0;
3479         for (i = 0;i < width * height;i++)
3480                 featuresmask |= palette_featureflags[skindata[i]];
3481
3482         skinframe->hasalpha = false;
3483         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3484         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3485         skinframe->qgeneratemerged = true;
3486         skinframe->qgeneratebase = skinframe->qhascolormapping;
3487         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3488
3489         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3490         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3491
3492         return skinframe;
3493 }
3494
3495 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3496 {
3497         int width;
3498         int height;
3499         unsigned char *skindata;
3500
3501         if (!skinframe->qpixels)
3502                 return;
3503
3504         if (!skinframe->qhascolormapping)
3505                 colormapped = false;
3506
3507         if (colormapped)
3508         {
3509                 if (!skinframe->qgeneratebase)
3510                         return;
3511         }
3512         else
3513         {
3514                 if (!skinframe->qgeneratemerged)
3515                         return;
3516         }
3517
3518         width = skinframe->qwidth;
3519         height = skinframe->qheight;
3520         skindata = skinframe->qpixels;
3521
3522         if (skinframe->qgeneratenmap)
3523         {
3524                 unsigned char *temp1, *temp2;
3525                 skinframe->qgeneratenmap = false;
3526                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3527                 temp2 = temp1 + width * height * 4;
3528                 // use either a custom palette or the quake palette
3529                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3530                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3531                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3532                 Mem_Free(temp1);
3533         }
3534
3535         if (skinframe->qgenerateglow)
3536         {
3537                 skinframe->qgenerateglow = false;
3538                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3539         }
3540
3541         if (colormapped)
3542         {
3543                 skinframe->qgeneratebase = false;
3544                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3545                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3546                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3547         }
3548         else
3549         {
3550                 skinframe->qgeneratemerged = false;
3551                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3552         }
3553
3554         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3555         {
3556                 Mem_Free(skinframe->qpixels);
3557                 skinframe->qpixels = NULL;
3558         }
3559 }
3560
3561 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3562 {
3563         int i;
3564         skinframe_t *skinframe;
3565
3566         if (cls.state == ca_dedicated)
3567                 return NULL;
3568
3569         // if already loaded just return it, otherwise make a new skinframe
3570         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3571         if (skinframe && skinframe->base)
3572                 return skinframe;
3573
3574         skinframe->stain = NULL;
3575         skinframe->merged = NULL;
3576         skinframe->base = NULL;
3577         skinframe->pants = NULL;
3578         skinframe->shirt = NULL;
3579         skinframe->nmap = NULL;
3580         skinframe->gloss = NULL;
3581         skinframe->glow = NULL;
3582         skinframe->fog = NULL;
3583         skinframe->reflect = NULL;
3584         skinframe->hasalpha = false;
3585
3586         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3587         if (!skindata)
3588                 return NULL;
3589
3590         if (developer_loading.integer)
3591                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3592
3593         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3594         if (textureflags & TEXF_ALPHA)
3595         {
3596                 for (i = 0;i < width * height;i++)
3597                 {
3598                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3599                         {
3600                                 skinframe->hasalpha = true;
3601                                 break;
3602                         }
3603                 }
3604                 if (r_loadfog && skinframe->hasalpha)
3605                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3606         }
3607
3608         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3609         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3610
3611         return skinframe;
3612 }
3613
3614 skinframe_t *R_SkinFrame_LoadMissing(void)
3615 {
3616         skinframe_t *skinframe;
3617
3618         if (cls.state == ca_dedicated)
3619                 return NULL;
3620
3621         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3622         skinframe->stain = NULL;
3623         skinframe->merged = NULL;
3624         skinframe->base = NULL;
3625         skinframe->pants = NULL;
3626         skinframe->shirt = NULL;
3627         skinframe->nmap = NULL;
3628         skinframe->gloss = NULL;
3629         skinframe->glow = NULL;
3630         skinframe->fog = NULL;
3631         skinframe->reflect = NULL;
3632         skinframe->hasalpha = false;
3633
3634         skinframe->avgcolor[0] = rand() / RAND_MAX;
3635         skinframe->avgcolor[1] = rand() / RAND_MAX;
3636         skinframe->avgcolor[2] = rand() / RAND_MAX;
3637         skinframe->avgcolor[3] = 1;
3638
3639         return skinframe;
3640 }
3641
3642 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3643 typedef struct suffixinfo_s
3644 {
3645         const char *suffix;
3646         qboolean flipx, flipy, flipdiagonal;
3647 }
3648 suffixinfo_t;
3649 static suffixinfo_t suffix[3][6] =
3650 {
3651         {
3652                 {"px",   false, false, false},
3653                 {"nx",   false, false, false},
3654                 {"py",   false, false, false},
3655                 {"ny",   false, false, false},
3656                 {"pz",   false, false, false},
3657                 {"nz",   false, false, false}
3658         },
3659         {
3660                 {"posx", false, false, false},
3661                 {"negx", false, false, false},
3662                 {"posy", false, false, false},
3663                 {"negy", false, false, false},
3664                 {"posz", false, false, false},
3665                 {"negz", false, false, false}
3666         },
3667         {
3668                 {"rt",    true, false,  true},
3669                 {"lf",   false,  true,  true},
3670                 {"ft",    true,  true, false},
3671                 {"bk",   false, false, false},
3672                 {"up",    true, false,  true},
3673                 {"dn",    true, false,  true}
3674         }
3675 };
3676
3677 static int componentorder[4] = {0, 1, 2, 3};
3678
3679 rtexture_t *R_LoadCubemap(const char *basename)
3680 {
3681         int i, j, cubemapsize;
3682         unsigned char *cubemappixels, *image_buffer;
3683         rtexture_t *cubemaptexture;
3684         char name[256];
3685         // must start 0 so the first loadimagepixels has no requested width/height
3686         cubemapsize = 0;
3687         cubemappixels = NULL;
3688         cubemaptexture = NULL;
3689         // keep trying different suffix groups (posx, px, rt) until one loads
3690         for (j = 0;j < 3 && !cubemappixels;j++)
3691         {
3692                 // load the 6 images in the suffix group
3693                 for (i = 0;i < 6;i++)
3694                 {
3695                         // generate an image name based on the base and and suffix
3696                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3697                         // load it
3698                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3699                         {
3700                                 // an image loaded, make sure width and height are equal
3701                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3702                                 {
3703                                         // if this is the first image to load successfully, allocate the cubemap memory
3704                                         if (!cubemappixels && image_width >= 1)
3705                                         {
3706                                                 cubemapsize = image_width;
3707                                                 // note this clears to black, so unavailable sides are black
3708                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3709                                         }
3710                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3711                                         if (cubemappixels)
3712                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3713                                 }
3714                                 else
3715                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3716                                 // free the image
3717                                 Mem_Free(image_buffer);
3718                         }
3719                 }
3720         }
3721         // if a cubemap loaded, upload it
3722         if (cubemappixels)
3723         {
3724                 if (developer_loading.integer)
3725                         Con_Printf("loading cubemap \"%s\"\n", basename);
3726
3727                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, r_texture_sRGB_cubemap.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3728                 Mem_Free(cubemappixels);
3729         }
3730         else
3731         {
3732                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3733                 if (developer_loading.integer)
3734                 {
3735                         Con_Printf("(tried tried images ");
3736                         for (j = 0;j < 3;j++)
3737                                 for (i = 0;i < 6;i++)
3738                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3739                         Con_Print(" and was unable to find any of them).\n");
3740                 }
3741         }
3742         return cubemaptexture;
3743 }
3744
3745 rtexture_t *R_GetCubemap(const char *basename)
3746 {
3747         int i;
3748         for (i = 0;i < r_texture_numcubemaps;i++)
3749                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3750                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3751         if (i >= MAX_CUBEMAPS)
3752                 return r_texture_whitecube;
3753         r_texture_numcubemaps++;
3754         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3755         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3756         return r_texture_cubemaps[i].texture;
3757 }
3758
3759 void R_FreeCubemaps(void)
3760 {
3761         int i;
3762         for (i = 0;i < r_texture_numcubemaps;i++)
3763         {
3764                 if (developer_loading.integer)
3765                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3766                 if (r_texture_cubemaps[i].texture)
3767                         R_FreeTexture(r_texture_cubemaps[i].texture);
3768         }
3769         r_texture_numcubemaps = 0;
3770 }
3771
3772 void R_Main_FreeViewCache(void)
3773 {
3774         if (r_refdef.viewcache.entityvisible)
3775                 Mem_Free(r_refdef.viewcache.entityvisible);
3776         if (r_refdef.viewcache.world_pvsbits)
3777                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3778         if (r_refdef.viewcache.world_leafvisible)
3779                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3780         if (r_refdef.viewcache.world_surfacevisible)
3781                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3782         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3783 }
3784
3785 void R_Main_ResizeViewCache(void)
3786 {
3787         int numentities = r_refdef.scene.numentities;
3788         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3789         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3790         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3791         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3792         if (r_refdef.viewcache.maxentities < numentities)
3793         {
3794                 r_refdef.viewcache.maxentities = numentities;
3795                 if (r_refdef.viewcache.entityvisible)
3796                         Mem_Free(r_refdef.viewcache.entityvisible);
3797                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3798         }
3799         if (r_refdef.viewcache.world_numclusters != numclusters)
3800         {
3801                 r_refdef.viewcache.world_numclusters = numclusters;
3802                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3803                 if (r_refdef.viewcache.world_pvsbits)
3804                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3805                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3806         }
3807         if (r_refdef.viewcache.world_numleafs != numleafs)
3808         {
3809                 r_refdef.viewcache.world_numleafs = numleafs;
3810                 if (r_refdef.viewcache.world_leafvisible)
3811                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3812                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3813         }
3814         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3815         {
3816                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3817                 if (r_refdef.viewcache.world_surfacevisible)
3818                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3819                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3820         }
3821 }
3822
3823 extern rtexture_t *loadingscreentexture;
3824 void gl_main_start(void)
3825 {
3826         loadingscreentexture = NULL;
3827         r_texture_blanknormalmap = NULL;
3828         r_texture_white = NULL;
3829         r_texture_grey128 = NULL;
3830         r_texture_black = NULL;
3831         r_texture_whitecube = NULL;
3832         r_texture_normalizationcube = NULL;
3833         r_texture_fogattenuation = NULL;
3834         r_texture_fogheighttexture = NULL;
3835         r_texture_gammaramps = NULL;
3836         r_texture_numcubemaps = 0;
3837
3838         r_loaddds = r_texture_dds_load.integer != 0;
3839         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3840
3841         switch(vid.renderpath)
3842         {
3843         case RENDERPATH_GL20:
3844         case RENDERPATH_D3D9:
3845         case RENDERPATH_D3D10:
3846         case RENDERPATH_D3D11:
3847         case RENDERPATH_SOFT:
3848         case RENDERPATH_GLES2:
3849                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3850                 Cvar_SetValueQuick(&gl_combine, 1);
3851                 Cvar_SetValueQuick(&r_glsl, 1);
3852                 r_loadnormalmap = true;
3853                 r_loadgloss = true;
3854                 r_loadfog = false;
3855                 break;
3856         case RENDERPATH_GL13:
3857         case RENDERPATH_GLES1:
3858                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3859                 Cvar_SetValueQuick(&gl_combine, 1);
3860                 Cvar_SetValueQuick(&r_glsl, 0);
3861                 r_loadnormalmap = false;
3862                 r_loadgloss = false;
3863                 r_loadfog = true;
3864                 break;
3865         case RENDERPATH_GL11:
3866                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3867                 Cvar_SetValueQuick(&gl_combine, 0);
3868                 Cvar_SetValueQuick(&r_glsl, 0);
3869                 r_loadnormalmap = false;
3870                 r_loadgloss = false;
3871                 r_loadfog = true;
3872                 break;
3873         }
3874
3875         R_AnimCache_Free();
3876         R_FrameData_Reset();
3877
3878         r_numqueries = 0;
3879         r_maxqueries = 0;
3880         memset(r_queries, 0, sizeof(r_queries));
3881
3882         r_qwskincache = NULL;
3883         r_qwskincache_size = 0;
3884
3885         // due to caching of texture_t references, the collision cache must be reset
3886         Collision_Cache_Reset(true);
3887
3888         // set up r_skinframe loading system for textures
3889         memset(&r_skinframe, 0, sizeof(r_skinframe));
3890         r_skinframe.loadsequence = 1;
3891         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3892
3893         r_main_texturepool = R_AllocTexturePool();
3894         R_BuildBlankTextures();
3895         R_BuildNoTexture();
3896         if (vid.support.arb_texture_cube_map)
3897         {
3898                 R_BuildWhiteCube();
3899                 R_BuildNormalizationCube();
3900         }
3901         r_texture_fogattenuation = NULL;
3902         r_texture_fogheighttexture = NULL;
3903         r_texture_gammaramps = NULL;
3904         //r_texture_fogintensity = NULL;
3905         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3906         memset(&r_waterstate, 0, sizeof(r_waterstate));
3907         r_glsl_permutation = NULL;
3908         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3909         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3910         glslshaderstring = NULL;
3911 #ifdef SUPPORTD3D
3912         r_hlsl_permutation = NULL;
3913         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3914         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3915 #endif
3916         hlslshaderstring = NULL;
3917         memset(&r_svbsp, 0, sizeof (r_svbsp));
3918
3919         r_refdef.fogmasktable_density = 0;
3920 }
3921
3922 void gl_main_shutdown(void)
3923 {
3924         R_AnimCache_Free();
3925         R_FrameData_Reset();
3926
3927         R_Main_FreeViewCache();
3928
3929         switch(vid.renderpath)
3930         {
3931         case RENDERPATH_GL11:
3932         case RENDERPATH_GL13:
3933         case RENDERPATH_GL20:
3934         case RENDERPATH_GLES1:
3935         case RENDERPATH_GLES2:
3936                 if (r_maxqueries)
3937                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3938                 break;
3939         case RENDERPATH_D3D9:
3940                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3941                 break;
3942         case RENDERPATH_D3D10:
3943                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3944                 break;
3945         case RENDERPATH_D3D11:
3946                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3947                 break;
3948         case RENDERPATH_SOFT:
3949                 break;
3950         }
3951
3952         r_numqueries = 0;
3953         r_maxqueries = 0;
3954         memset(r_queries, 0, sizeof(r_queries));
3955
3956         r_qwskincache = NULL;
3957         r_qwskincache_size = 0;
3958
3959         // clear out the r_skinframe state
3960         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3961         memset(&r_skinframe, 0, sizeof(r_skinframe));
3962
3963         if (r_svbsp.nodes)
3964                 Mem_Free(r_svbsp.nodes);
3965         memset(&r_svbsp, 0, sizeof (r_svbsp));
3966         R_FreeTexturePool(&r_main_texturepool);
3967         loadingscreentexture = NULL;
3968         r_texture_blanknormalmap = NULL;
3969         r_texture_white = NULL;
3970         r_texture_grey128 = NULL;
3971         r_texture_black = NULL;
3972         r_texture_whitecube = NULL;
3973         r_texture_normalizationcube = NULL;
3974         r_texture_fogattenuation = NULL;
3975         r_texture_fogheighttexture = NULL;
3976         r_texture_gammaramps = NULL;
3977         r_texture_numcubemaps = 0;
3978         //r_texture_fogintensity = NULL;
3979         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3980         memset(&r_waterstate, 0, sizeof(r_waterstate));
3981         R_GLSL_Restart_f();
3982
3983         r_glsl_permutation = NULL;
3984         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3985         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3986         glslshaderstring = NULL;
3987 #ifdef SUPPORTD3D
3988         r_hlsl_permutation = NULL;
3989         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3990         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3991 #endif
3992         hlslshaderstring = NULL;
3993 }
3994
3995 extern void CL_ParseEntityLump(char *entitystring);
3996 void gl_main_newmap(void)
3997 {
3998         // FIXME: move this code to client
3999         char *entities, entname[MAX_QPATH];
4000         if (r_qwskincache)
4001                 Mem_Free(r_qwskincache);
4002         r_qwskincache = NULL;
4003         r_qwskincache_size = 0;
4004         if (cl.worldmodel)
4005         {
4006                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4007                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4008                 {
4009                         CL_ParseEntityLump(entities);
4010                         Mem_Free(entities);
4011                         return;
4012                 }
4013                 if (cl.worldmodel->brush.entities)
4014                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4015         }
4016         R_Main_FreeViewCache();
4017
4018         R_FrameData_Reset();
4019 }
4020
4021 void GL_Main_Init(void)
4022 {
4023         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4024
4025         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4026         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4027         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4028         if (gamemode == GAME_NEHAHRA)
4029         {
4030                 Cvar_RegisterVariable (&gl_fogenable);
4031                 Cvar_RegisterVariable (&gl_fogdensity);
4032                 Cvar_RegisterVariable (&gl_fogred);
4033                 Cvar_RegisterVariable (&gl_foggreen);
4034                 Cvar_RegisterVariable (&gl_fogblue);
4035                 Cvar_RegisterVariable (&gl_fogstart);
4036                 Cvar_RegisterVariable (&gl_fogend);
4037                 Cvar_RegisterVariable (&gl_skyclip);
4038         }
4039         Cvar_RegisterVariable(&r_motionblur);
4040         Cvar_RegisterVariable(&r_motionblur_maxblur);
4041         Cvar_RegisterVariable(&r_motionblur_bmin);
4042         Cvar_RegisterVariable(&r_motionblur_vmin);
4043         Cvar_RegisterVariable(&r_motionblur_vmax);
4044         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4045         Cvar_RegisterVariable(&r_motionblur_randomize);
4046         Cvar_RegisterVariable(&r_damageblur);
4047         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4048         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4049         Cvar_RegisterVariable(&r_equalize_entities_by);
4050         Cvar_RegisterVariable(&r_equalize_entities_to);
4051         Cvar_RegisterVariable(&r_depthfirst);
4052         Cvar_RegisterVariable(&r_useinfinitefarclip);
4053         Cvar_RegisterVariable(&r_farclip_base);
4054         Cvar_RegisterVariable(&r_farclip_world);
4055         Cvar_RegisterVariable(&r_nearclip);
4056         Cvar_RegisterVariable(&r_deformvertexes);
4057         Cvar_RegisterVariable(&r_transparent);
4058         Cvar_RegisterVariable(&r_showoverdraw);
4059         Cvar_RegisterVariable(&r_showbboxes);
4060         Cvar_RegisterVariable(&r_showsurfaces);
4061         Cvar_RegisterVariable(&r_showtris);
4062         Cvar_RegisterVariable(&r_shownormals);
4063         Cvar_RegisterVariable(&r_showlighting);
4064         Cvar_RegisterVariable(&r_showshadowvolumes);
4065         Cvar_RegisterVariable(&r_showcollisionbrushes);
4066         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4067         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4068         Cvar_RegisterVariable(&r_showdisabledepthtest);
4069         Cvar_RegisterVariable(&r_drawportals);
4070         Cvar_RegisterVariable(&r_drawentities);
4071         Cvar_RegisterVariable(&r_draw2d);
4072         Cvar_RegisterVariable(&r_drawworld);
4073         Cvar_RegisterVariable(&r_cullentities_trace);
4074         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4075         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4076         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4077         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4078         Cvar_RegisterVariable(&r_drawviewmodel);
4079         Cvar_RegisterVariable(&r_drawexteriormodel);
4080         Cvar_RegisterVariable(&r_speeds);
4081         Cvar_RegisterVariable(&r_fullbrights);
4082         Cvar_RegisterVariable(&r_wateralpha);
4083         Cvar_RegisterVariable(&r_dynamic);
4084         Cvar_RegisterVariable(&r_fakelight);
4085         Cvar_RegisterVariable(&r_fakelight_intensity);
4086         Cvar_RegisterVariable(&r_fullbright);
4087         Cvar_RegisterVariable(&r_shadows);
4088         Cvar_RegisterVariable(&r_shadows_darken);
4089         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4090         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4091         Cvar_RegisterVariable(&r_shadows_throwdistance);
4092         Cvar_RegisterVariable(&r_shadows_throwdirection);
4093         Cvar_RegisterVariable(&r_shadows_focus);
4094         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4095         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4096         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4097         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4098         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4099         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4100         Cvar_RegisterVariable(&r_fog_exp2);
4101         Cvar_RegisterVariable(&r_fog_clear);
4102         Cvar_RegisterVariable(&r_drawfog);
4103         Cvar_RegisterVariable(&r_transparentdepthmasking);
4104         Cvar_RegisterVariable(&r_texture_dds_load);
4105         Cvar_RegisterVariable(&r_texture_dds_save);
4106         Cvar_RegisterVariable(&r_texture_sRGB_2d);
4107         Cvar_RegisterVariable(&r_texture_sRGB_skin_diffuse);
4108         Cvar_RegisterVariable(&r_texture_sRGB_skin_gloss);
4109         Cvar_RegisterVariable(&r_texture_sRGB_skin_glow);
4110         Cvar_RegisterVariable(&r_texture_sRGB_skin_reflect);
4111         Cvar_RegisterVariable(&r_texture_sRGB_cubemap);
4112         Cvar_RegisterVariable(&r_texture_sRGB_skybox);
4113         Cvar_RegisterVariable(&r_textureunits);
4114         Cvar_RegisterVariable(&gl_combine);
4115         Cvar_RegisterVariable(&r_viewfbo);
4116         Cvar_RegisterVariable(&r_viewscale);
4117         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4118         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4119         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4120         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4121         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4122         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4123         Cvar_RegisterVariable(&r_glsl);
4124         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4125         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4126         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4127         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4128         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4129         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4130         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4131         Cvar_RegisterVariable(&r_glsl_postprocess);
4132         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4133         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4134         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4135         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4136         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4137         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4138         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4139         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4140
4141         Cvar_RegisterVariable(&r_water);
4142         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4143         Cvar_RegisterVariable(&r_water_clippingplanebias);
4144         Cvar_RegisterVariable(&r_water_refractdistort);
4145         Cvar_RegisterVariable(&r_water_reflectdistort);
4146         Cvar_RegisterVariable(&r_water_scissormode);
4147         Cvar_RegisterVariable(&r_lerpsprites);
4148         Cvar_RegisterVariable(&r_lerpmodels);
4149         Cvar_RegisterVariable(&r_lerplightstyles);
4150         Cvar_RegisterVariable(&r_waterscroll);
4151         Cvar_RegisterVariable(&r_bloom);
4152         Cvar_RegisterVariable(&r_bloom_colorscale);
4153         Cvar_RegisterVariable(&r_bloom_brighten);
4154         Cvar_RegisterVariable(&r_bloom_blur);
4155         Cvar_RegisterVariable(&r_bloom_resolution);
4156         Cvar_RegisterVariable(&r_bloom_colorexponent);
4157         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4158         Cvar_RegisterVariable(&r_hdr);
4159         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4160         Cvar_RegisterVariable(&r_hdr_glowintensity);
4161         Cvar_RegisterVariable(&r_hdr_range);
4162         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4163         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4164         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4165         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4166         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4167         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4168         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4169         Cvar_RegisterVariable(&developer_texturelogging);
4170         Cvar_RegisterVariable(&gl_lightmaps);
4171         Cvar_RegisterVariable(&r_test);
4172         Cvar_RegisterVariable(&r_glsl_saturation);
4173         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4174         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4175         Cvar_RegisterVariable(&r_framedatasize);
4176         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4177                 Cvar_SetValue("r_fullbrights", 0);
4178         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4179
4180         Cvar_RegisterVariable(&r_track_sprites);
4181         Cvar_RegisterVariable(&r_track_sprites_flags);
4182         Cvar_RegisterVariable(&r_track_sprites_scalew);
4183         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4184         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4185         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4186         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4187         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4188 }
4189
4190 extern void R_Textures_Init(void);
4191 extern void GL_Draw_Init(void);
4192 extern void GL_Main_Init(void);
4193 extern void R_Shadow_Init(void);
4194 extern void R_Sky_Init(void);
4195 extern void GL_Surf_Init(void);
4196 extern void R_Particles_Init(void);
4197 extern void R_Explosion_Init(void);
4198 extern void gl_backend_init(void);
4199 extern void Sbar_Init(void);
4200 extern void R_LightningBeams_Init(void);
4201 extern void Mod_RenderInit(void);
4202 extern void Font_Init(void);
4203
4204 void Render_Init(void)
4205 {
4206         gl_backend_init();
4207         R_Textures_Init();
4208         GL_Main_Init();
4209         Font_Init();
4210         GL_Draw_Init();
4211         R_Shadow_Init();
4212         R_Sky_Init();
4213         GL_Surf_Init();
4214         Sbar_Init();
4215         R_Particles_Init();
4216         R_Explosion_Init();
4217         R_LightningBeams_Init();
4218         Mod_RenderInit();
4219 }
4220
4221 /*
4222 ===============
4223 GL_Init
4224 ===============
4225 */
4226 extern char *ENGINE_EXTENSIONS;
4227 void GL_Init (void)
4228 {
4229         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4230         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4231         gl_version = (const char *)qglGetString(GL_VERSION);
4232         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4233
4234         if (!gl_extensions)
4235                 gl_extensions = "";
4236         if (!gl_platformextensions)
4237                 gl_platformextensions = "";
4238
4239         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4240         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4241         Con_Printf("GL_VERSION: %s\n", gl_version);
4242         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4243         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4244
4245         VID_CheckExtensions();
4246
4247         // LordHavoc: report supported extensions
4248         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4249
4250         // clear to black (loading plaque will be seen over this)
4251         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4252 }
4253
4254 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4255 {
4256         int i;
4257         mplane_t *p;
4258         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4259         {
4260                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4261                 if (i == 4)
4262                         continue;
4263                 p = r_refdef.view.frustum + i;
4264                 switch(p->signbits)
4265                 {
4266                 default:
4267                 case 0:
4268                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4269                                 return true;
4270                         break;
4271                 case 1:
4272                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4273                                 return true;
4274                         break;
4275                 case 2:
4276                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4277                                 return true;
4278                         break;
4279                 case 3:
4280                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4281                                 return true;
4282                         break;
4283                 case 4:
4284                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4285                                 return true;
4286                         break;
4287                 case 5:
4288                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4289                                 return true;
4290                         break;
4291                 case 6:
4292                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4293                                 return true;
4294                         break;
4295                 case 7:
4296                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4297                                 return true;
4298                         break;
4299                 }
4300         }
4301         return false;
4302 }
4303
4304 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4305 {
4306         int i;
4307         const mplane_t *p;
4308         for (i = 0;i < numplanes;i++)
4309         {
4310                 p = planes + i;
4311                 switch(p->signbits)
4312                 {
4313                 default:
4314                 case 0:
4315                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4316                                 return true;
4317                         break;
4318                 case 1:
4319                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4320                                 return true;
4321                         break;
4322                 case 2:
4323                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4324                                 return true;
4325                         break;
4326                 case 3:
4327                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4328                                 return true;
4329                         break;
4330                 case 4:
4331                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4332                                 return true;
4333                         break;
4334                 case 5:
4335                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4336                                 return true;
4337                         break;
4338                 case 6:
4339                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4340                                 return true;
4341                         break;
4342                 case 7:
4343                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4344                                 return true;
4345                         break;
4346                 }
4347         }
4348         return false;
4349 }
4350
4351 //==================================================================================
4352
4353 // LordHavoc: this stores temporary data used within the same frame
4354
4355 typedef struct r_framedata_mem_s
4356 {
4357         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4358         size_t size; // how much usable space
4359         size_t current; // how much space in use
4360         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4361         size_t wantedsize; // how much space was allocated
4362         unsigned char *data; // start of real data (16byte aligned)
4363 }
4364 r_framedata_mem_t;
4365
4366 static r_framedata_mem_t *r_framedata_mem;
4367
4368 void R_FrameData_Reset(void)
4369 {
4370         while (r_framedata_mem)
4371         {
4372                 r_framedata_mem_t *next = r_framedata_mem->purge;
4373                 Mem_Free(r_framedata_mem);
4374                 r_framedata_mem = next;
4375         }
4376 }
4377
4378 void R_FrameData_Resize(void)
4379 {
4380         size_t wantedsize;
4381         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4382         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4383         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4384         {
4385                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4386                 newmem->wantedsize = wantedsize;
4387                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4388                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4389                 newmem->current = 0;
4390                 newmem->mark = 0;
4391                 newmem->purge = r_framedata_mem;
4392                 r_framedata_mem = newmem;
4393         }
4394 }
4395
4396 void R_FrameData_NewFrame(void)
4397 {
4398         R_FrameData_Resize();
4399         if (!r_framedata_mem)
4400                 return;
4401         // if we ran out of space on the last frame, free the old memory now
4402         while (r_framedata_mem->purge)
4403         {
4404                 // repeatedly remove the second item in the list, leaving only head
4405                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4406                 Mem_Free(r_framedata_mem->purge);
4407                 r_framedata_mem->purge = next;
4408         }
4409         // reset the current mem pointer
4410         r_framedata_mem->current = 0;
4411         r_framedata_mem->mark = 0;
4412 }
4413
4414 void *R_FrameData_Alloc(size_t size)
4415 {
4416         void *data;
4417
4418         // align to 16 byte boundary - the data pointer is already aligned, so we
4419         // only need to ensure the size of every allocation is also aligned
4420         size = (size + 15) & ~15;
4421
4422         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4423         {
4424                 // emergency - we ran out of space, allocate more memory
4425                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4426                 R_FrameData_Resize();
4427         }
4428
4429         data = r_framedata_mem->data + r_framedata_mem->current;
4430         r_framedata_mem->current += size;
4431
4432         // count the usage for stats
4433         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4434         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4435
4436         return (void *)data;
4437 }
4438
4439 void *R_FrameData_Store(size_t size, void *data)
4440 {
4441         void *d = R_FrameData_Alloc(size);
4442         if (d && data)
4443                 memcpy(d, data, size);
4444         return d;
4445 }
4446
4447 void R_FrameData_SetMark(void)
4448 {
4449         if (!r_framedata_mem)
4450                 return;
4451         r_framedata_mem->mark = r_framedata_mem->current;
4452 }
4453
4454 void R_FrameData_ReturnToMark(void)
4455 {
4456         if (!r_framedata_mem)
4457                 return;
4458         r_framedata_mem->current = r_framedata_mem->mark;
4459 }
4460
4461 //==================================================================================
4462
4463 // LordHavoc: animcache originally written by Echon, rewritten since then
4464
4465 /**
4466  * Animation cache prevents re-generating mesh data for an animated model
4467  * multiple times in one frame for lighting, shadowing, reflections, etc.
4468  */
4469
4470 void R_AnimCache_Free(void)
4471 {
4472 }
4473
4474 void R_AnimCache_ClearCache(void)
4475 {
4476         int i;
4477         entity_render_t *ent;
4478
4479         for (i = 0;i < r_refdef.scene.numentities;i++)
4480         {
4481                 ent = r_refdef.scene.entities[i];
4482                 ent->animcache_vertex3f = NULL;
4483                 ent->animcache_normal3f = NULL;
4484                 ent->animcache_svector3f = NULL;
4485                 ent->animcache_tvector3f = NULL;
4486                 ent->animcache_vertexmesh = NULL;
4487                 ent->animcache_vertex3fbuffer = NULL;
4488                 ent->animcache_vertexmeshbuffer = NULL;
4489         }
4490 }
4491
4492 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4493 {
4494         int i;
4495
4496         // check if we need the meshbuffers
4497         if (!vid.useinterleavedarrays)
4498                 return;
4499
4500         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4501                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4502         // TODO: upload vertex3f buffer?
4503         if (ent->animcache_vertexmesh)
4504         {
4505                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4506                 for (i = 0;i < numvertices;i++)
4507                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4508                 if (ent->animcache_svector3f)
4509                         for (i = 0;i < numvertices;i++)
4510                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4511                 if (ent->animcache_tvector3f)
4512                         for (i = 0;i < numvertices;i++)
4513                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4514                 if (ent->animcache_normal3f)
4515                         for (i = 0;i < numvertices;i++)
4516                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4517                 // TODO: upload vertexmeshbuffer?
4518         }
4519 }
4520
4521 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4522 {
4523         dp_model_t *model = ent->model;
4524         int numvertices;
4525         // see if it's already cached this frame
4526         if (ent->animcache_vertex3f)
4527         {
4528                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4529                 if (wantnormals || wanttangents)
4530                 {
4531                         if (ent->animcache_normal3f)
4532                                 wantnormals = false;
4533                         if (ent->animcache_svector3f)
4534                                 wanttangents = false;
4535                         if (wantnormals || wanttangents)
4536                         {
4537                                 numvertices = model->surfmesh.num_vertices;
4538                                 if (wantnormals)
4539                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4540                                 if (wanttangents)
4541                                 {
4542                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4543                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4544                                 }
4545                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4546                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4547                         }
4548                 }
4549         }
4550         else
4551         {
4552                 // see if this ent is worth caching
4553                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4554                         return false;
4555                 // get some memory for this entity and generate mesh data
4556                 numvertices = model->surfmesh.num_vertices;
4557                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4558                 if (wantnormals)
4559                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4560                 if (wanttangents)
4561                 {
4562                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4563                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4564                 }
4565                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4566                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4567         }
4568         return true;
4569 }
4570
4571 void R_AnimCache_CacheVisibleEntities(void)
4572 {
4573         int i;
4574         qboolean wantnormals = true;
4575         qboolean wanttangents = !r_showsurfaces.integer;
4576
4577         switch(vid.renderpath)
4578         {
4579         case RENDERPATH_GL20:
4580         case RENDERPATH_D3D9:
4581         case RENDERPATH_D3D10:
4582         case RENDERPATH_D3D11:
4583         case RENDERPATH_GLES2:
4584                 break;
4585         case RENDERPATH_GL11:
4586         case RENDERPATH_GL13:
4587         case RENDERPATH_GLES1:
4588                 wanttangents = false;
4589                 break;
4590         case RENDERPATH_SOFT:
4591                 break;
4592         }
4593
4594         if (r_shownormals.integer)
4595                 wanttangents = wantnormals = true;
4596
4597         // TODO: thread this
4598         // NOTE: R_PrepareRTLights() also caches entities
4599
4600         for (i = 0;i < r_refdef.scene.numentities;i++)
4601                 if (r_refdef.viewcache.entityvisible[i])
4602                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4603 }
4604
4605 //==================================================================================
4606
4607 static void R_View_UpdateEntityLighting (void)
4608 {
4609         int i;
4610         entity_render_t *ent;
4611         vec3_t tempdiffusenormal, avg;
4612         vec_t f, fa, fd, fdd;
4613         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4614
4615         for (i = 0;i < r_refdef.scene.numentities;i++)
4616         {
4617                 ent = r_refdef.scene.entities[i];
4618
4619                 // skip unseen models
4620                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4621                         continue;
4622
4623                 // skip bsp models
4624                 if (ent->model && ent->model->brush.num_leafs)
4625                 {
4626                         // TODO: use modellight for r_ambient settings on world?
4627                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4628                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4629                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4630                         continue;
4631                 }
4632
4633                 // fetch the lighting from the worldmodel data
4634                 VectorClear(ent->modellight_ambient);
4635                 VectorClear(ent->modellight_diffuse);
4636                 VectorClear(tempdiffusenormal);
4637                 if (ent->flags & RENDER_LIGHT)
4638                 {
4639                         vec3_t org;
4640                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4641
4642                         // complete lightning for lit sprites
4643                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4644                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4645                         {
4646                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4647                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4648                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4649                         }
4650                         else
4651                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4652
4653                         if(ent->flags & RENDER_EQUALIZE)
4654                         {
4655                                 // first fix up ambient lighting...
4656                                 if(r_equalize_entities_minambient.value > 0)
4657                                 {
4658                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4659                                         if(fd > 0)
4660                                         {
4661                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4662                                                 if(fa < r_equalize_entities_minambient.value * fd)
4663                                                 {
4664                                                         // solve:
4665                                                         //   fa'/fd' = minambient
4666                                                         //   fa'+0.25*fd' = fa+0.25*fd
4667                                                         //   ...
4668                                                         //   fa' = fd' * minambient
4669                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4670                                                         //   ...
4671                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4672                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4673                                                         //   ...
4674                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4675                                                         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
4676                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4677                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4678                                                 }
4679                                         }
4680                                 }
4681
4682                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4683                                 {
4684                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4685                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4686                                         f = fa + 0.25 * fd;
4687                                         if(f > 0)
4688                                         {
4689                                                 // adjust brightness and saturation to target
4690                                                 avg[0] = avg[1] = avg[2] = fa / f;
4691                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4692                                                 avg[0] = avg[1] = avg[2] = fd / f;
4693                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4694                                         }
4695                                 }
4696                         }
4697                 }
4698                 else // highly rare
4699                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4700
4701                 // move the light direction into modelspace coordinates for lighting code
4702                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4703                 if(VectorLength2(ent->modellight_lightdir) == 0)
4704                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4705                 VectorNormalize(ent->modellight_lightdir);
4706         }
4707 }
4708
4709 #define MAX_LINEOFSIGHTTRACES 64
4710
4711 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4712 {
4713         int i;
4714         vec3_t boxmins, boxmaxs;
4715         vec3_t start;
4716         vec3_t end;
4717         dp_model_t *model = r_refdef.scene.worldmodel;
4718
4719         if (!model || !model->brush.TraceLineOfSight)
4720                 return true;
4721
4722         // expand the box a little
4723         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4724         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4725         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4726         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4727         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4728         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4729
4730         // return true if eye is inside enlarged box
4731         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4732                 return true;
4733
4734         // try center
4735         VectorCopy(eye, start);
4736         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4737         if (model->brush.TraceLineOfSight(model, start, end))
4738                 return true;
4739
4740         // try various random positions
4741         for (i = 0;i < numsamples;i++)
4742         {
4743                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4744                 if (model->brush.TraceLineOfSight(model, start, end))
4745                         return true;
4746         }
4747
4748         return false;
4749 }
4750
4751
4752 static void R_View_UpdateEntityVisible (void)
4753 {
4754         int i;
4755         int renderimask;
4756         int samples;
4757         entity_render_t *ent;
4758
4759         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4760                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4761                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4762                 :                                                          RENDER_EXTERIORMODEL;
4763         if (!r_drawviewmodel.integer)
4764                 renderimask |= RENDER_VIEWMODEL;
4765         if (!r_drawexteriormodel.integer)
4766                 renderimask |= RENDER_EXTERIORMODEL;
4767         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4768         {
4769                 // worldmodel can check visibility
4770                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4771                 for (i = 0;i < r_refdef.scene.numentities;i++)
4772                 {
4773                         ent = r_refdef.scene.entities[i];
4774                         if (!(ent->flags & renderimask))
4775                         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)))
4776                         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))
4777                                 r_refdef.viewcache.entityvisible[i] = true;
4778                 }
4779         }
4780         else
4781         {
4782                 // no worldmodel or it can't check visibility
4783                 for (i = 0;i < r_refdef.scene.numentities;i++)
4784                 {
4785                         ent = r_refdef.scene.entities[i];
4786                         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));
4787                 }
4788         }
4789         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4790                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4791         {
4792                 for (i = 0;i < r_refdef.scene.numentities;i++)
4793                 {
4794                         if (!r_refdef.viewcache.entityvisible[i])
4795                                 continue;
4796                         ent = r_refdef.scene.entities[i];
4797                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4798                         {
4799                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4800                                 if (samples < 0)
4801                                         continue; // temp entities do pvs only
4802                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4803                                         ent->last_trace_visibility = realtime;
4804                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4805                                         r_refdef.viewcache.entityvisible[i] = 0;
4806                         }
4807                 }
4808         }
4809 }
4810
4811 /// only used if skyrendermasked, and normally returns false
4812 int R_DrawBrushModelsSky (void)
4813 {
4814         int i, sky;
4815         entity_render_t *ent;
4816
4817         sky = false;
4818         for (i = 0;i < r_refdef.scene.numentities;i++)
4819         {
4820                 if (!r_refdef.viewcache.entityvisible[i])
4821                         continue;
4822                 ent = r_refdef.scene.entities[i];
4823                 if (!ent->model || !ent->model->DrawSky)
4824                         continue;
4825                 ent->model->DrawSky(ent);
4826                 sky = true;
4827         }
4828         return sky;
4829 }
4830
4831 static void R_DrawNoModel(entity_render_t *ent);
4832 static void R_DrawModels(void)
4833 {
4834         int i;
4835         entity_render_t *ent;
4836
4837         for (i = 0;i < r_refdef.scene.numentities;i++)
4838         {
4839                 if (!r_refdef.viewcache.entityvisible[i])
4840                         continue;
4841                 ent = r_refdef.scene.entities[i];
4842                 r_refdef.stats.entities++;
4843                 if (ent->model && ent->model->Draw != NULL)
4844                         ent->model->Draw(ent);
4845                 else
4846                         R_DrawNoModel(ent);
4847         }
4848 }
4849
4850 static void R_DrawModelsDepth(void)
4851 {
4852         int i;
4853         entity_render_t *ent;
4854
4855         for (i = 0;i < r_refdef.scene.numentities;i++)
4856         {
4857                 if (!r_refdef.viewcache.entityvisible[i])
4858                         continue;
4859                 ent = r_refdef.scene.entities[i];
4860                 if (ent->model && ent->model->DrawDepth != NULL)
4861                         ent->model->DrawDepth(ent);
4862         }
4863 }
4864
4865 static void R_DrawModelsDebug(void)
4866 {
4867         int i;
4868         entity_render_t *ent;
4869
4870         for (i = 0;i < r_refdef.scene.numentities;i++)
4871         {
4872                 if (!r_refdef.viewcache.entityvisible[i])
4873                         continue;
4874                 ent = r_refdef.scene.entities[i];
4875                 if (ent->model && ent->model->DrawDebug != NULL)
4876                         ent->model->DrawDebug(ent);
4877         }
4878 }
4879
4880 static void R_DrawModelsAddWaterPlanes(void)
4881 {
4882         int i;
4883         entity_render_t *ent;
4884
4885         for (i = 0;i < r_refdef.scene.numentities;i++)
4886         {
4887                 if (!r_refdef.viewcache.entityvisible[i])
4888                         continue;
4889                 ent = r_refdef.scene.entities[i];
4890                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4891                         ent->model->DrawAddWaterPlanes(ent);
4892         }
4893 }
4894
4895 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4896 {
4897         if (r_hdr_irisadaptation.integer)
4898         {
4899                 vec3_t ambient;
4900                 vec3_t diffuse;
4901                 vec3_t diffusenormal;
4902                 vec_t brightness;
4903                 vec_t goal;
4904                 vec_t adjust;
4905                 vec_t current;
4906                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4907                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4908                 brightness = max(0.0000001f, brightness);
4909                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4910                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4911                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4912                 current = r_hdr_irisadaptation_value.value;
4913                 if (current < goal)
4914                         current = min(current + adjust, goal);
4915                 else if (current > goal)
4916                         current = max(current - adjust, goal);
4917                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4918                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4919         }
4920         else if (r_hdr_irisadaptation_value.value != 1.0f)
4921                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4922 }
4923
4924 static void R_View_SetFrustum(const int *scissor)
4925 {
4926         int i;
4927         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4928         vec3_t forward, left, up, origin, v;
4929
4930         if(scissor)
4931         {
4932                 // flipped x coordinates (because x points left here)
4933                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4934                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4935
4936                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4937                 switch(vid.renderpath)
4938                 {
4939                         case RENDERPATH_D3D9:
4940                         case RENDERPATH_D3D10:
4941                         case RENDERPATH_D3D11:
4942                                 // non-flipped y coordinates
4943                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4944                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4945                                 break;
4946                         case RENDERPATH_SOFT:
4947                         case RENDERPATH_GL11:
4948                         case RENDERPATH_GL13:
4949                         case RENDERPATH_GL20:
4950                         case RENDERPATH_GLES1:
4951                         case RENDERPATH_GLES2:
4952                                 // non-flipped y coordinates
4953                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4954                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4955                                 break;
4956                 }
4957         }
4958
4959         // we can't trust r_refdef.view.forward and friends in reflected scenes
4960         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4961
4962 #if 0
4963         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4964         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4965         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4966         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4967         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4968         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4969         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4970         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4971         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4972         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4973         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4974         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4975 #endif
4976
4977 #if 0
4978         zNear = r_refdef.nearclip;
4979         nudge = 1.0 - 1.0 / (1<<23);
4980         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4981         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4982         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4983         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4984         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4985         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4986         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4987         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4988 #endif
4989
4990
4991
4992 #if 0
4993         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4994         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4995         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4996         r_refdef.view.frustum[0].dist = m[15] - m[12];
4997
4998         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4999         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5000         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5001         r_refdef.view.frustum[1].dist = m[15] + m[12];
5002
5003         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5004         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5005         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5006         r_refdef.view.frustum[2].dist = m[15] - m[13];
5007
5008         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5009         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5010         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5011         r_refdef.view.frustum[3].dist = m[15] + m[13];
5012
5013         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5014         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5015         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5016         r_refdef.view.frustum[4].dist = m[15] - m[14];
5017
5018         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5019         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5020         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5021         r_refdef.view.frustum[5].dist = m[15] + m[14];
5022 #endif
5023
5024         if (r_refdef.view.useperspective)
5025         {
5026                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5027                 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]);
5028                 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]);
5029                 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]);
5030                 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]);
5031
5032                 // then the normals from the corners relative to origin
5033                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5034                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5035                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5036                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5037
5038                 // in a NORMAL view, forward cross left == up
5039                 // in a REFLECTED view, forward cross left == down
5040                 // so our cross products above need to be adjusted for a left handed coordinate system
5041                 CrossProduct(forward, left, v);
5042                 if(DotProduct(v, up) < 0)
5043                 {
5044                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5045                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5046                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5047                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5048                 }
5049
5050                 // Leaving those out was a mistake, those were in the old code, and they
5051                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5052                 // I couldn't reproduce it after adding those normalizations. --blub
5053                 VectorNormalize(r_refdef.view.frustum[0].normal);
5054                 VectorNormalize(r_refdef.view.frustum[1].normal);
5055                 VectorNormalize(r_refdef.view.frustum[2].normal);
5056                 VectorNormalize(r_refdef.view.frustum[3].normal);
5057
5058                 // make the corners absolute
5059                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5060                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5061                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5062                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5063
5064                 // one more normal
5065                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5066
5067                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5068                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5069                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5070                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5071                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5072         }
5073         else
5074         {
5075                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5076                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5077                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5078                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5079                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5080                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5081                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5082                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5083                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5084                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5085         }
5086         r_refdef.view.numfrustumplanes = 5;
5087
5088         if (r_refdef.view.useclipplane)
5089         {
5090                 r_refdef.view.numfrustumplanes = 6;
5091                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5092         }
5093
5094         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5095                 PlaneClassify(r_refdef.view.frustum + i);
5096
5097         // LordHavoc: note to all quake engine coders, Quake had a special case
5098         // for 90 degrees which assumed a square view (wrong), so I removed it,
5099         // Quake2 has it disabled as well.
5100
5101         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5102         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5103         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5104         //PlaneClassify(&frustum[0]);
5105
5106         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5107         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5108         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5109         //PlaneClassify(&frustum[1]);
5110
5111         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5112         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5113         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5114         //PlaneClassify(&frustum[2]);
5115
5116         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5117         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5118         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5119         //PlaneClassify(&frustum[3]);
5120
5121         // nearclip plane
5122         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5123         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5124         //PlaneClassify(&frustum[4]);
5125 }
5126
5127 void R_View_UpdateWithScissor(const int *myscissor)
5128 {
5129         R_Main_ResizeViewCache();
5130         R_View_SetFrustum(myscissor);
5131         R_View_WorldVisibility(r_refdef.view.useclipplane);
5132         R_View_UpdateEntityVisible();
5133         R_View_UpdateEntityLighting();
5134 }
5135
5136 void R_View_Update(void)
5137 {
5138         R_Main_ResizeViewCache();
5139         R_View_SetFrustum(NULL);
5140         R_View_WorldVisibility(r_refdef.view.useclipplane);
5141         R_View_UpdateEntityVisible();
5142         R_View_UpdateEntityLighting();
5143 }
5144
5145 float viewscalefpsadjusted = 1.0f;
5146
5147 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5148 {
5149         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5150         scale = bound(0.03125f, scale, 1.0f);
5151         *outwidth = (int)ceil(width * scale);
5152         *outheight = (int)ceil(height * scale);
5153 }
5154
5155 void R_Mesh_SetMainRenderTargets(void)
5156 {
5157         if (r_bloomstate.fbo_framebuffer)
5158                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5159         else
5160                 R_Mesh_ResetRenderTargets();
5161 }
5162
5163 void R_SetupView(qboolean allowwaterclippingplane)
5164 {
5165         const float *customclipplane = NULL;
5166         float plane[4];
5167         int scaledwidth, scaledheight;
5168         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5169         {
5170                 // LordHavoc: couldn't figure out how to make this approach the
5171                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5172                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5173                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5174                         dist = r_refdef.view.clipplane.dist;
5175                 plane[0] = r_refdef.view.clipplane.normal[0];
5176                 plane[1] = r_refdef.view.clipplane.normal[1];
5177                 plane[2] = r_refdef.view.clipplane.normal[2];
5178                 plane[3] = -dist;
5179                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5180         }
5181
5182         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5183         if (!r_refdef.view.useperspective)
5184                 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);
5185         else if (vid.stencil && r_useinfinitefarclip.integer)
5186                 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);
5187         else
5188                 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);
5189         R_Mesh_SetMainRenderTargets();
5190         R_SetViewport(&r_refdef.view.viewport);
5191         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5192         {
5193                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5194                 float screenplane[4];
5195                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5196                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5197                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5198                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5199                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5200         }
5201 }
5202
5203 void R_EntityMatrix(const matrix4x4_t *matrix)
5204 {
5205         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5206         {
5207                 gl_modelmatrixchanged = false;
5208                 gl_modelmatrix = *matrix;
5209                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5210                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5211                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5212                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5213                 CHECKGLERROR
5214                 switch(vid.renderpath)
5215                 {
5216                 case RENDERPATH_D3D9:
5217 #ifdef SUPPORTD3D
5218                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5219                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5220 #endif
5221                         break;
5222                 case RENDERPATH_D3D10:
5223                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5224                         break;
5225                 case RENDERPATH_D3D11:
5226                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5227                         break;
5228                 case RENDERPATH_GL11:
5229                 case RENDERPATH_GL13:
5230                 case RENDERPATH_GLES1:
5231                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5232                         break;
5233                 case RENDERPATH_SOFT:
5234                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5235                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5236                         break;
5237                 case RENDERPATH_GL20:
5238                 case RENDERPATH_GLES2:
5239                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5240                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5241                         break;
5242                 }
5243         }
5244 }
5245
5246 void R_ResetViewRendering2D(void)
5247 {
5248         r_viewport_t viewport;
5249         DrawQ_Finish();
5250
5251         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5252         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);
5253         R_Mesh_ResetRenderTargets();
5254         R_SetViewport(&viewport);
5255         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5256         GL_Color(1, 1, 1, 1);
5257         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5258         GL_BlendFunc(GL_ONE, GL_ZERO);
5259         GL_ScissorTest(false);
5260         GL_DepthMask(false);
5261         GL_DepthRange(0, 1);
5262         GL_DepthTest(false);
5263         GL_DepthFunc(GL_LEQUAL);
5264         R_EntityMatrix(&identitymatrix);
5265         R_Mesh_ResetTextureState();
5266         GL_PolygonOffset(0, 0);
5267         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5268         switch(vid.renderpath)
5269         {
5270         case RENDERPATH_GL11:
5271         case RENDERPATH_GL13:
5272         case RENDERPATH_GL20:
5273         case RENDERPATH_GLES1:
5274         case RENDERPATH_GLES2:
5275                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5276                 break;
5277         case RENDERPATH_D3D9:
5278         case RENDERPATH_D3D10:
5279         case RENDERPATH_D3D11:
5280         case RENDERPATH_SOFT:
5281                 break;
5282         }
5283         GL_CullFace(GL_NONE);
5284 }
5285
5286 void R_ResetViewRendering3D(void)
5287 {
5288         DrawQ_Finish();
5289
5290         R_SetupView(true);
5291         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5292         GL_Color(1, 1, 1, 1);
5293         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5294         GL_BlendFunc(GL_ONE, GL_ZERO);
5295         GL_ScissorTest(true);
5296         GL_DepthMask(true);
5297         GL_DepthRange(0, 1);
5298         GL_DepthTest(true);
5299         GL_DepthFunc(GL_LEQUAL);
5300         R_EntityMatrix(&identitymatrix);
5301         R_Mesh_ResetTextureState();
5302         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5303         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5304         switch(vid.renderpath)
5305         {
5306         case RENDERPATH_GL11:
5307         case RENDERPATH_GL13:
5308         case RENDERPATH_GL20:
5309         case RENDERPATH_GLES1:
5310         case RENDERPATH_GLES2:
5311                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5312                 break;
5313         case RENDERPATH_D3D9:
5314         case RENDERPATH_D3D10:
5315         case RENDERPATH_D3D11:
5316         case RENDERPATH_SOFT:
5317                 break;
5318         }
5319         GL_CullFace(r_refdef.view.cullface_back);
5320 }
5321
5322 /*
5323 ================
5324 R_RenderView_UpdateViewVectors
5325 ================
5326 */
5327 static void R_RenderView_UpdateViewVectors(void)
5328 {
5329         // break apart the view matrix into vectors for various purposes
5330         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5331         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5332         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5333         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5334         // make an inverted copy of the view matrix for tracking sprites
5335         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5336 }
5337
5338 void R_RenderScene(void);
5339 void R_RenderWaterPlanes(void);
5340
5341 static void R_Water_StartFrame(void)
5342 {
5343         int i;
5344         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5345         r_waterstate_waterplane_t *p;
5346
5347         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5348                 return;
5349
5350         switch(vid.renderpath)
5351         {
5352         case RENDERPATH_GL20:
5353         case RENDERPATH_D3D9:
5354         case RENDERPATH_D3D10:
5355         case RENDERPATH_D3D11:
5356         case RENDERPATH_SOFT:
5357         case RENDERPATH_GLES2:
5358                 break;
5359         case RENDERPATH_GL11:
5360         case RENDERPATH_GL13:
5361         case RENDERPATH_GLES1:
5362                 return;
5363         }
5364
5365         // set waterwidth and waterheight to the water resolution that will be
5366         // used (often less than the screen resolution for faster rendering)
5367         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5368         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5369
5370         // calculate desired texture sizes
5371         // can't use water if the card does not support the texture size
5372         if (!r_water.integer || r_showsurfaces.integer)
5373                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5374         else if (vid.support.arb_texture_non_power_of_two)
5375         {
5376                 texturewidth = waterwidth;
5377                 textureheight = waterheight;
5378                 camerawidth = waterwidth;
5379                 cameraheight = waterheight;
5380         }
5381         else
5382         {
5383                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5384                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5385                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5386                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5387         }
5388
5389         // allocate textures as needed
5390         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5391         {
5392                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5393                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5394                 {
5395                         if (p->texture_refraction)
5396                                 R_FreeTexture(p->texture_refraction);
5397                         p->texture_refraction = NULL;
5398                         if (p->texture_reflection)
5399                                 R_FreeTexture(p->texture_reflection);
5400                         p->texture_reflection = NULL;
5401                         if (p->texture_camera)
5402                                 R_FreeTexture(p->texture_camera);
5403                         p->texture_camera = NULL;
5404                 }
5405                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5406                 r_waterstate.texturewidth = texturewidth;
5407                 r_waterstate.textureheight = textureheight;
5408                 r_waterstate.camerawidth = camerawidth;
5409                 r_waterstate.cameraheight = cameraheight;
5410         }
5411
5412         if (r_waterstate.texturewidth)
5413         {
5414                 r_waterstate.enabled = true;
5415
5416                 // when doing a reduced render (HDR) we want to use a smaller area
5417                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5418                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5419
5420                 // set up variables that will be used in shader setup
5421                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5422                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5423                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5424                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5425         }
5426
5427         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5428         r_waterstate.numwaterplanes = 0;
5429 }
5430
5431 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5432 {
5433         int triangleindex, planeindex;
5434         const int *e;
5435         vec3_t vert[3];
5436         vec3_t normal;
5437         vec3_t center;
5438         mplane_t plane;
5439         r_waterstate_waterplane_t *p;
5440         texture_t *t = R_GetCurrentTexture(surface->texture);
5441
5442         // just use the first triangle with a valid normal for any decisions
5443         VectorClear(normal);
5444         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5445         {
5446                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5447                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5448                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5449                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5450                 if (VectorLength2(normal) >= 0.001)
5451                         break;
5452         }
5453
5454         VectorCopy(normal, plane.normal);
5455         VectorNormalize(plane.normal);
5456         plane.dist = DotProduct(vert[0], plane.normal);
5457         PlaneClassify(&plane);
5458         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5459         {
5460                 // skip backfaces (except if nocullface is set)
5461                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5462                         return;
5463                 VectorNegate(plane.normal, plane.normal);
5464                 plane.dist *= -1;
5465                 PlaneClassify(&plane);
5466         }
5467
5468
5469         // find a matching plane if there is one
5470         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5471                 if(p->camera_entity == t->camera_entity)
5472                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5473                                 break;
5474         if (planeindex >= r_waterstate.maxwaterplanes)
5475                 return; // nothing we can do, out of planes
5476
5477         // if this triangle does not fit any known plane rendered this frame, add one
5478         if (planeindex >= r_waterstate.numwaterplanes)
5479         {
5480                 // store the new plane
5481                 r_waterstate.numwaterplanes++;
5482                 p->plane = plane;
5483                 // clear materialflags and pvs
5484                 p->materialflags = 0;
5485                 p->pvsvalid = false;
5486                 p->camera_entity = t->camera_entity;
5487                 VectorCopy(surface->mins, p->mins);
5488                 VectorCopy(surface->maxs, p->maxs);
5489         }
5490         else
5491         {
5492                 // merge mins/maxs
5493                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5494                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5495                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5496                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5497                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5498                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5499         }
5500         // merge this surface's materialflags into the waterplane
5501         p->materialflags |= t->currentmaterialflags;
5502         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5503         {
5504                 // merge this surface's PVS into the waterplane
5505                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5506                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5507                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5508                 {
5509                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5510                         p->pvsvalid = true;
5511                 }
5512         }
5513 }
5514
5515 static void R_Water_ProcessPlanes(void)
5516 {
5517         int myscissor[4];
5518         r_refdef_view_t originalview;
5519         r_refdef_view_t myview;
5520         int planeindex;
5521         r_waterstate_waterplane_t *p;
5522         vec3_t visorigin;
5523
5524         originalview = r_refdef.view;
5525
5526         // make sure enough textures are allocated
5527         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5528         {
5529                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5530                 {
5531                         if (!p->texture_refraction)
5532                                 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);
5533                         if (!p->texture_refraction)
5534                                 goto error;
5535                 }
5536                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5537                 {
5538                         if (!p->texture_camera)
5539                                 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);
5540                         if (!p->texture_camera)
5541                                 goto error;
5542                 }
5543
5544                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5545                 {
5546                         if (!p->texture_reflection)
5547                                 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);
5548                         if (!p->texture_reflection)
5549                                 goto error;
5550                 }
5551         }
5552
5553         // render views
5554         r_refdef.view = originalview;
5555         r_refdef.view.showdebug = false;
5556         r_refdef.view.width = r_waterstate.waterwidth;
5557         r_refdef.view.height = r_waterstate.waterheight;
5558         r_refdef.view.useclipplane = true;
5559         myview = r_refdef.view;
5560         r_waterstate.renderingscene = true;
5561         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5562         {
5563                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5564                 {
5565                         r_refdef.view = myview;
5566                         if(r_water_scissormode.integer)
5567                         {
5568                                 R_SetupView(true);
5569                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5570                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5571                         }
5572
5573                         // render reflected scene and copy into texture
5574                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5575                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5576                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5577                         r_refdef.view.clipplane = p->plane;
5578
5579                         // reverse the cullface settings for this render
5580                         r_refdef.view.cullface_front = GL_FRONT;
5581                         r_refdef.view.cullface_back = GL_BACK;
5582                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5583                         {
5584                                 r_refdef.view.usecustompvs = true;
5585                                 if (p->pvsvalid)
5586                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5587                                 else
5588                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5589                         }
5590
5591                         R_ResetViewRendering3D();
5592                         R_ClearScreen(r_refdef.fogenabled);
5593                         if(r_water_scissormode.integer & 2)
5594                                 R_View_UpdateWithScissor(myscissor);
5595                         else
5596                                 R_View_Update();
5597                         if(r_water_scissormode.integer & 1)
5598                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5599                         R_RenderScene();
5600
5601                         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);
5602                 }
5603
5604                 // render the normal view scene and copy into texture
5605                 // (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)
5606                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5607                 {
5608                         r_refdef.view = myview;
5609                         if(r_water_scissormode.integer)
5610                         {
5611                                 R_SetupView(true);
5612                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5613                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5614                         }
5615
5616                         r_waterstate.renderingrefraction = true;
5617
5618                         r_refdef.view.clipplane = p->plane;
5619                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5620                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5621
5622                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5623                         {
5624                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5625                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5626                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5627                                 R_RenderView_UpdateViewVectors();
5628                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5629                                 {
5630                                         r_refdef.view.usecustompvs = true;
5631                                         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);
5632                                 }
5633                         }
5634
5635                         PlaneClassify(&r_refdef.view.clipplane);
5636
5637                         R_ResetViewRendering3D();
5638                         R_ClearScreen(r_refdef.fogenabled);
5639                         if(r_water_scissormode.integer & 2)
5640                                 R_View_UpdateWithScissor(myscissor);
5641                         else
5642                                 R_View_Update();
5643                         if(r_water_scissormode.integer & 1)
5644                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5645                         R_RenderScene();
5646
5647                         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);
5648                         r_waterstate.renderingrefraction = false;
5649                 }
5650                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5651                 {
5652                         r_refdef.view = myview;
5653
5654                         r_refdef.view.clipplane = p->plane;
5655                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5656                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5657
5658                         r_refdef.view.width = r_waterstate.camerawidth;
5659                         r_refdef.view.height = r_waterstate.cameraheight;
5660                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5661                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5662
5663                         if(p->camera_entity)
5664                         {
5665                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5666                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5667                         }
5668
5669                         // note: all of the view is used for displaying... so
5670                         // there is no use in scissoring
5671
5672                         // reverse the cullface settings for this render
5673                         r_refdef.view.cullface_front = GL_FRONT;
5674                         r_refdef.view.cullface_back = GL_BACK;
5675                         // also reverse the view matrix
5676                         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
5677                         R_RenderView_UpdateViewVectors();
5678                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5679                         {
5680                                 r_refdef.view.usecustompvs = true;
5681                                 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);
5682                         }
5683                         
5684                         // camera needs no clipplane
5685                         r_refdef.view.useclipplane = false;
5686
5687                         PlaneClassify(&r_refdef.view.clipplane);
5688
5689                         R_ResetViewRendering3D();
5690                         R_ClearScreen(r_refdef.fogenabled);
5691                         R_View_Update();
5692                         R_RenderScene();
5693
5694                         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);
5695                         r_waterstate.renderingrefraction = false;
5696                 }
5697
5698         }
5699         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5700         r_waterstate.renderingscene = false;
5701         r_refdef.view = originalview;
5702         R_ResetViewRendering3D();
5703         R_ClearScreen(r_refdef.fogenabled);
5704         R_View_Update();
5705         return;
5706 error:
5707         r_refdef.view = originalview;
5708         r_waterstate.renderingscene = false;
5709         Cvar_SetValueQuick(&r_water, 0);
5710         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5711         return;
5712 }
5713
5714 void R_Bloom_StartFrame(void)
5715 {
5716         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5717         int viewwidth, viewheight;
5718         textype_t textype;
5719
5720         if (r_viewscale_fpsscaling.integer)
5721         {
5722                 double actualframetime;
5723                 double targetframetime;
5724                 double adjust;
5725                 actualframetime = r_refdef.lastdrawscreentime;
5726                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5727                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5728                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5729                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5730                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5731                 viewscalefpsadjusted += adjust;
5732                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5733         }
5734         else
5735                 viewscalefpsadjusted = 1.0f;
5736
5737         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5738
5739         switch(vid.renderpath)
5740         {
5741         case RENDERPATH_GL20:
5742         case RENDERPATH_D3D9:
5743         case RENDERPATH_D3D10:
5744         case RENDERPATH_D3D11:
5745         case RENDERPATH_SOFT:
5746         case RENDERPATH_GLES2:
5747                 break;
5748         case RENDERPATH_GL11:
5749         case RENDERPATH_GL13:
5750         case RENDERPATH_GLES1:
5751                 return;
5752         }
5753
5754         // set bloomwidth and bloomheight to the bloom resolution that will be
5755         // used (often less than the screen resolution for faster rendering)
5756         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5757         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5758         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5759         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5760         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5761
5762         // calculate desired texture sizes
5763         if (vid.support.arb_texture_non_power_of_two)
5764         {
5765                 screentexturewidth = vid.width;
5766                 screentextureheight = vid.height;
5767                 bloomtexturewidth = r_bloomstate.bloomwidth;
5768                 bloomtextureheight = r_bloomstate.bloomheight;
5769         }
5770         else
5771         {
5772                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5773                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5774                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5775                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5776         }
5777
5778         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))
5779         {
5780                 Cvar_SetValueQuick(&r_hdr, 0);
5781                 Cvar_SetValueQuick(&r_bloom, 0);
5782                 Cvar_SetValueQuick(&r_motionblur, 0);
5783                 Cvar_SetValueQuick(&r_damageblur, 0);
5784         }
5785
5786         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)
5787                 screentexturewidth = screentextureheight = 0;
5788         if (!r_hdr.integer && !r_bloom.integer)
5789                 bloomtexturewidth = bloomtextureheight = 0;
5790
5791         textype = TEXTYPE_COLORBUFFER;
5792         switch (vid.renderpath)
5793         {
5794         case RENDERPATH_GL20:
5795         case RENDERPATH_GLES2:
5796                 if (vid.support.ext_framebuffer_object)
5797                 {
5798                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5799                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5800                 }
5801                 break;
5802         case RENDERPATH_GL11:
5803         case RENDERPATH_GL13:
5804         case RENDERPATH_GLES1:
5805         case RENDERPATH_D3D9:
5806         case RENDERPATH_D3D10:
5807         case RENDERPATH_D3D11:
5808         case RENDERPATH_SOFT:
5809                 break;
5810         }
5811
5812         // allocate textures as needed
5813         if (r_bloomstate.screentexturewidth != screentexturewidth
5814          || r_bloomstate.screentextureheight != screentextureheight
5815          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5816          || r_bloomstate.bloomtextureheight != bloomtextureheight
5817          || r_bloomstate.texturetype != textype
5818          || r_bloomstate.viewfbo != r_viewfbo.integer)
5819         {
5820                 if (r_bloomstate.texture_bloom)
5821                         R_FreeTexture(r_bloomstate.texture_bloom);
5822                 r_bloomstate.texture_bloom = NULL;
5823                 if (r_bloomstate.texture_screen)
5824                         R_FreeTexture(r_bloomstate.texture_screen);
5825                 r_bloomstate.texture_screen = NULL;
5826                 if (r_bloomstate.fbo_framebuffer)
5827                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5828                 r_bloomstate.fbo_framebuffer = 0;
5829                 if (r_bloomstate.texture_framebuffercolor)
5830                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5831                 r_bloomstate.texture_framebuffercolor = NULL;
5832                 if (r_bloomstate.texture_framebufferdepth)
5833                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5834                 r_bloomstate.texture_framebufferdepth = NULL;
5835                 r_bloomstate.screentexturewidth = screentexturewidth;
5836                 r_bloomstate.screentextureheight = screentextureheight;
5837                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5838                         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);
5839                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5840                 {
5841                         // FIXME: choose depth bits based on a cvar
5842                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5843                         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);
5844                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5845                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5846                         // render depth into one texture and normalmap into the other
5847                         if (qglDrawBuffer)
5848                         {
5849                                 int status;
5850                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5851                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5852                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5853                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5854                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5855                         }
5856                 }
5857                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5858                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5859                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5860                         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);
5861                 r_bloomstate.viewfbo = r_viewfbo.integer;
5862                 r_bloomstate.texturetype = textype;
5863         }
5864
5865         // when doing a reduced render (HDR) we want to use a smaller area
5866         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5867         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5868         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5869         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5870         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5871
5872         // set up a texcoord array for the full resolution screen image
5873         // (we have to keep this around to copy back during final render)
5874         r_bloomstate.screentexcoord2f[0] = 0;
5875         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5876         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5877         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5878         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5879         r_bloomstate.screentexcoord2f[5] = 0;
5880         r_bloomstate.screentexcoord2f[6] = 0;
5881         r_bloomstate.screentexcoord2f[7] = 0;
5882
5883         // set up a texcoord array for the reduced resolution bloom image
5884         // (which will be additive blended over the screen image)
5885         r_bloomstate.bloomtexcoord2f[0] = 0;
5886         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5887         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5888         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5889         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5890         r_bloomstate.bloomtexcoord2f[5] = 0;
5891         r_bloomstate.bloomtexcoord2f[6] = 0;
5892         r_bloomstate.bloomtexcoord2f[7] = 0;
5893
5894         switch(vid.renderpath)
5895         {
5896         case RENDERPATH_GL11:
5897         case RENDERPATH_GL13:
5898         case RENDERPATH_GL20:
5899         case RENDERPATH_SOFT:
5900         case RENDERPATH_GLES1:
5901         case RENDERPATH_GLES2:
5902                 break;
5903         case RENDERPATH_D3D9:
5904         case RENDERPATH_D3D10:
5905         case RENDERPATH_D3D11:
5906                 {
5907                         int i;
5908                         for (i = 0;i < 4;i++)
5909                         {
5910                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5911                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5912                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5913                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5914                         }
5915                 }
5916                 break;
5917         }
5918
5919         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5920         {
5921                 r_bloomstate.enabled = true;
5922                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5923         }
5924
5925         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);
5926
5927         if (r_bloomstate.fbo_framebuffer)
5928                 r_refdef.view.clear = true;
5929 }
5930
5931 void R_Bloom_CopyBloomTexture(float colorscale)
5932 {
5933         r_refdef.stats.bloom++;
5934
5935         // scale down screen texture to the bloom texture size
5936         CHECKGLERROR
5937         R_Mesh_SetMainRenderTargets();
5938         R_SetViewport(&r_bloomstate.viewport);
5939         GL_BlendFunc(GL_ONE, GL_ZERO);
5940         GL_Color(colorscale, colorscale, colorscale, 1);
5941         // 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...
5942         switch(vid.renderpath)
5943         {
5944         case RENDERPATH_GL11:
5945         case RENDERPATH_GL13:
5946         case RENDERPATH_GL20:
5947         case RENDERPATH_GLES1:
5948         case RENDERPATH_GLES2:
5949         case RENDERPATH_SOFT:
5950                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5951                 break;
5952         case RENDERPATH_D3D9:
5953         case RENDERPATH_D3D10:
5954         case RENDERPATH_D3D11:
5955                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5956                 break;
5957         }
5958         // TODO: do boxfilter scale-down in shader?
5959         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5960         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5961         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5962
5963         // we now have a bloom image in the framebuffer
5964         // copy it into the bloom image texture for later processing
5965         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);
5966         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5967 }
5968
5969 void R_Bloom_CopyHDRTexture(void)
5970 {
5971         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);
5972         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5973 }
5974
5975 void R_Bloom_MakeTexture(void)
5976 {
5977         int x, range, dir;
5978         float xoffset, yoffset, r, brighten;
5979
5980         r_refdef.stats.bloom++;
5981
5982         R_ResetViewRendering2D();
5983
5984         // we have a bloom image in the framebuffer
5985         CHECKGLERROR
5986         R_SetViewport(&r_bloomstate.viewport);
5987
5988         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5989         {
5990                 x *= 2;
5991                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5992                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5993                 GL_Color(r,r,r,1);
5994                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5995                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5996                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5997                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5998
5999                 // copy the vertically blurred bloom view to a texture
6000                 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);
6001                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6002         }
6003
6004         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6005         brighten = r_bloom_brighten.value;
6006         if (r_bloomstate.hdr)
6007                 brighten *= r_hdr_range.value;
6008         brighten = sqrt(brighten);
6009         if(range >= 1)
6010                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6011         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6012
6013         for (dir = 0;dir < 2;dir++)
6014         {
6015                 // blend on at multiple vertical offsets to achieve a vertical blur
6016                 // TODO: do offset blends using GLSL
6017                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6018                 GL_BlendFunc(GL_ONE, GL_ZERO);
6019                 for (x = -range;x <= range;x++)
6020                 {
6021                         if (!dir){xoffset = 0;yoffset = x;}
6022                         else {xoffset = x;yoffset = 0;}
6023                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6024                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6025                         // compute a texcoord array with the specified x and y offset
6026                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6027                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6028                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6029                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6030                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6031                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6032                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6033                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6034                         // this r value looks like a 'dot' particle, fading sharply to
6035                         // black at the edges
6036                         // (probably not realistic but looks good enough)
6037                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6038                         //r = brighten/(range*2+1);
6039                         r = brighten / (range * 2 + 1);
6040                         if(range >= 1)
6041                                 r *= (1 - x*x/(float)(range*range));
6042                         GL_Color(r, r, r, 1);
6043                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6044                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6045                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6046                         GL_BlendFunc(GL_ONE, GL_ONE);
6047                 }
6048
6049                 // copy the vertically blurred bloom view to a texture
6050                 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);
6051                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6052         }
6053 }
6054
6055 void R_HDR_RenderBloomTexture(void)
6056 {
6057         int oldwidth, oldheight;
6058         float oldcolorscale;
6059         qboolean oldwaterstate;
6060
6061         oldwaterstate = r_waterstate.enabled;
6062         oldcolorscale = r_refdef.view.colorscale;
6063         oldwidth = r_refdef.view.width;
6064         oldheight = r_refdef.view.height;
6065         r_refdef.view.width = r_bloomstate.bloomwidth;
6066         r_refdef.view.height = r_bloomstate.bloomheight;
6067
6068         if(r_hdr.integer < 2)
6069                 r_waterstate.enabled = false;
6070
6071         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6072         // TODO: add exposure compensation features
6073         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6074
6075         r_refdef.view.showdebug = false;
6076         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6077
6078         R_ResetViewRendering3D();
6079
6080         R_ClearScreen(r_refdef.fogenabled);
6081         if (r_timereport_active)
6082                 R_TimeReport("HDRclear");
6083
6084         R_View_Update();
6085         if (r_timereport_active)
6086                 R_TimeReport("visibility");
6087
6088         // only do secondary renders with HDR if r_hdr is 2 or higher
6089         r_waterstate.numwaterplanes = 0;
6090         if (r_waterstate.enabled)
6091                 R_RenderWaterPlanes();
6092
6093         r_refdef.view.showdebug = true;
6094         R_RenderScene();
6095         r_waterstate.numwaterplanes = 0;
6096
6097         R_ResetViewRendering2D();
6098
6099         R_Bloom_CopyHDRTexture();
6100         R_Bloom_MakeTexture();
6101
6102         // restore the view settings
6103         r_waterstate.enabled = oldwaterstate;
6104         r_refdef.view.width = oldwidth;
6105         r_refdef.view.height = oldheight;
6106         r_refdef.view.colorscale = oldcolorscale;
6107
6108         R_ResetViewRendering3D();
6109
6110         R_ClearScreen(r_refdef.fogenabled);
6111         if (r_timereport_active)
6112                 R_TimeReport("viewclear");
6113 }
6114
6115 static void R_BlendView(void)
6116 {
6117         unsigned int permutation;
6118         float uservecs[4][4];
6119
6120         switch (vid.renderpath)
6121         {
6122         case RENDERPATH_GL20:
6123         case RENDERPATH_D3D9:
6124         case RENDERPATH_D3D10:
6125         case RENDERPATH_D3D11:
6126         case RENDERPATH_SOFT:
6127         case RENDERPATH_GLES2:
6128                 permutation =
6129                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6130                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6131                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6132                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6133                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6134
6135                 if (r_bloomstate.texture_screen)
6136                 {
6137                         // make sure the buffer is available
6138                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6139
6140                         R_ResetViewRendering2D();
6141                         R_Mesh_SetMainRenderTargets();
6142
6143                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6144                         {
6145                                 // declare variables
6146                                 float speed;
6147                                 static float avgspeed;
6148
6149                                 speed = VectorLength(cl.movement_velocity);
6150
6151                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6152                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6153
6154                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6155                                 speed = bound(0, speed, 1);
6156                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6157
6158                                 // calculate values into a standard alpha
6159                                 cl.motionbluralpha = 1 - exp(-
6160                                                 (
6161                                                  (r_motionblur.value * speed / 80)
6162                                                  +
6163                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6164                                                 )
6165                                                 /
6166                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6167                                            );
6168
6169                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6170                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6171                                 // apply the blur
6172                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6173                                 {
6174                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6175                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6176                                         switch(vid.renderpath)
6177                                         {
6178                                         case RENDERPATH_GL11:
6179                                         case RENDERPATH_GL13:
6180                                         case RENDERPATH_GL20:
6181                                         case RENDERPATH_GLES1:
6182                                         case RENDERPATH_GLES2:
6183                                         case RENDERPATH_SOFT:
6184                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6185                                                 break;
6186                                         case RENDERPATH_D3D9:
6187                                         case RENDERPATH_D3D10:
6188                                         case RENDERPATH_D3D11:
6189                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6190                                                 break;
6191                                         }
6192                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6193                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6194                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6195                                 }
6196                         }
6197
6198                         // copy view into the screen texture
6199                         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);
6200                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6201                 }
6202                 else if (!r_bloomstate.texture_bloom)
6203                 {
6204                         // we may still have to do view tint...
6205                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6206                         {
6207                                 // apply a color tint to the whole view
6208                                 R_ResetViewRendering2D();
6209                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6210                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6211                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6212                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6213                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6214                         }
6215                         break; // no screen processing, no bloom, skip it
6216                 }
6217
6218                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6219                 {
6220                         // render simple bloom effect
6221                         // copy the screen and shrink it and darken it for the bloom process
6222                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6223                         // make the bloom texture
6224                         R_Bloom_MakeTexture();
6225                 }
6226
6227 #if _MSC_VER >= 1400
6228 #define sscanf sscanf_s
6229 #endif
6230                 memset(uservecs, 0, sizeof(uservecs));
6231                 if (r_glsl_postprocess_uservec1_enable.integer)
6232                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6233                 if (r_glsl_postprocess_uservec2_enable.integer)
6234                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6235                 if (r_glsl_postprocess_uservec3_enable.integer)
6236                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6237                 if (r_glsl_postprocess_uservec4_enable.integer)
6238                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6239
6240                 R_ResetViewRendering2D();
6241                 GL_Color(1, 1, 1, 1);
6242                 GL_BlendFunc(GL_ONE, GL_ZERO);
6243
6244                 switch(vid.renderpath)
6245                 {
6246                 case RENDERPATH_GL20:
6247                 case RENDERPATH_GLES2:
6248                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6249                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6250                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6251                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6252                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6253                         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]);
6254                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6255                         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]);
6256                         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]);
6257                         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]);
6258                         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]);
6259                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6260                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6261                         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);
6262                         break;
6263                 case RENDERPATH_D3D9:
6264 #ifdef SUPPORTD3D
6265                         // 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...
6266                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6267                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6268                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6269                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6270                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6271                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6272                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6273                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6274                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6275                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6276                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6277                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6278                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6279                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6280 #endif
6281                         break;
6282                 case RENDERPATH_D3D10:
6283                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6284                         break;
6285                 case RENDERPATH_D3D11:
6286                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6287                         break;
6288                 case RENDERPATH_SOFT:
6289                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6290                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6291                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6292                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6293                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6294                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6295                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6296                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6297                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6298                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6299                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6300                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6301                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6302                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6303                         break;
6304                 default:
6305                         break;
6306                 }
6307                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6308                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6309                 break;
6310         case RENDERPATH_GL11:
6311         case RENDERPATH_GL13:
6312         case RENDERPATH_GLES1:
6313                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6314                 {
6315                         // apply a color tint to the whole view
6316                         R_ResetViewRendering2D();
6317                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6318                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6319                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6320                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6321                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6322                 }
6323                 break;
6324         }
6325 }
6326
6327 matrix4x4_t r_waterscrollmatrix;
6328
6329 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6330 {
6331         if (r_refdef.fog_density)
6332         {
6333                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6334                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6335                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6336
6337                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6338                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6339                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6340                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6341
6342                 {
6343                         vec3_t fogvec;
6344                         VectorCopy(r_refdef.fogcolor, fogvec);
6345                         //   color.rgb *= ContrastBoost * SceneBrightness;
6346                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6347                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6348                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6349                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6350                 }
6351         }
6352 }
6353
6354 void R_UpdateVariables(void)
6355 {
6356         R_Textures_Frame();
6357
6358         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6359
6360         r_refdef.farclip = r_farclip_base.value;
6361         if (r_refdef.scene.worldmodel)
6362                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6363         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6364
6365         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6366                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6367         r_refdef.polygonfactor = 0;
6368         r_refdef.polygonoffset = 0;
6369         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6370         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6371
6372         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6373         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6374         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6375         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6376         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6377         if (FAKELIGHT_ENABLED)
6378         {
6379                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6380         }
6381         if (r_showsurfaces.integer)
6382         {
6383                 r_refdef.scene.rtworld = false;
6384                 r_refdef.scene.rtworldshadows = false;
6385                 r_refdef.scene.rtdlight = false;
6386                 r_refdef.scene.rtdlightshadows = false;
6387                 r_refdef.lightmapintensity = 0;
6388         }
6389
6390         if (gamemode == GAME_NEHAHRA)
6391         {
6392                 if (gl_fogenable.integer)
6393                 {
6394                         r_refdef.oldgl_fogenable = true;
6395                         r_refdef.fog_density = gl_fogdensity.value;
6396                         r_refdef.fog_red = gl_fogred.value;
6397                         r_refdef.fog_green = gl_foggreen.value;
6398                         r_refdef.fog_blue = gl_fogblue.value;
6399                         r_refdef.fog_alpha = 1;
6400                         r_refdef.fog_start = 0;
6401                         r_refdef.fog_end = gl_skyclip.value;
6402                         r_refdef.fog_height = 1<<30;
6403                         r_refdef.fog_fadedepth = 128;
6404                 }
6405                 else if (r_refdef.oldgl_fogenable)
6406                 {
6407                         r_refdef.oldgl_fogenable = false;
6408                         r_refdef.fog_density = 0;
6409                         r_refdef.fog_red = 0;
6410                         r_refdef.fog_green = 0;
6411                         r_refdef.fog_blue = 0;
6412                         r_refdef.fog_alpha = 0;
6413                         r_refdef.fog_start = 0;
6414                         r_refdef.fog_end = 0;
6415                         r_refdef.fog_height = 1<<30;
6416                         r_refdef.fog_fadedepth = 128;
6417                 }
6418         }
6419
6420         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6421         r_refdef.fog_start = max(0, r_refdef.fog_start);
6422         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6423
6424         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6425
6426         if (r_refdef.fog_density && r_drawfog.integer)
6427         {
6428                 r_refdef.fogenabled = true;
6429                 // this is the point where the fog reaches 0.9986 alpha, which we
6430                 // consider a good enough cutoff point for the texture
6431                 // (0.9986 * 256 == 255.6)
6432                 if (r_fog_exp2.integer)
6433                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6434                 else
6435                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6436                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6437                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6438                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6439                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6440                         R_BuildFogHeightTexture();
6441                 // fog color was already set
6442                 // update the fog texture
6443                 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)
6444                         R_BuildFogTexture();
6445                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6446                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6447         }
6448         else
6449                 r_refdef.fogenabled = false;
6450
6451         switch(vid.renderpath)
6452         {
6453         case RENDERPATH_GL20:
6454         case RENDERPATH_D3D9:
6455         case RENDERPATH_D3D10:
6456         case RENDERPATH_D3D11:
6457         case RENDERPATH_SOFT:
6458         case RENDERPATH_GLES2:
6459                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6460                 {
6461                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6462                         {
6463                                 // build GLSL gamma texture
6464 #define RAMPWIDTH 256
6465                                 unsigned short ramp[RAMPWIDTH * 3];
6466                                 unsigned char rampbgr[RAMPWIDTH][4];
6467                                 int i;
6468
6469                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6470
6471                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6472                                 for(i = 0; i < RAMPWIDTH; ++i)
6473                                 {
6474                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6475                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6476                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6477                                         rampbgr[i][3] = 0;
6478                                 }
6479                                 if (r_texture_gammaramps)
6480                                 {
6481                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6482                                 }
6483                                 else
6484                                 {
6485                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6486                                 }
6487                         }
6488                 }
6489                 else
6490                 {
6491                         // remove GLSL gamma texture
6492                 }
6493                 break;
6494         case RENDERPATH_GL11:
6495         case RENDERPATH_GL13:
6496         case RENDERPATH_GLES1:
6497                 break;
6498         }
6499 }
6500
6501 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6502 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6503 /*
6504 ================
6505 R_SelectScene
6506 ================
6507 */
6508 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6509         if( scenetype != r_currentscenetype ) {
6510                 // store the old scenetype
6511                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6512                 r_currentscenetype = scenetype;
6513                 // move in the new scene
6514                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6515         }
6516 }
6517
6518 /*
6519 ================
6520 R_GetScenePointer
6521 ================
6522 */
6523 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6524 {
6525         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6526         if( scenetype == r_currentscenetype ) {
6527                 return &r_refdef.scene;
6528         } else {
6529                 return &r_scenes_store[ scenetype ];
6530         }
6531 }
6532
6533 /*
6534 ================
6535 R_RenderView
6536 ================
6537 */
6538 int dpsoftrast_test;
6539 void R_RenderView(void)
6540 {
6541         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6542
6543         dpsoftrast_test = r_test.integer;
6544
6545         if (r_timereport_active)
6546                 R_TimeReport("start");
6547         r_textureframe++; // used only by R_GetCurrentTexture
6548         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6549
6550         if(R_CompileShader_CheckStaticParms())
6551                 R_GLSL_Restart_f();
6552
6553         if (!r_drawentities.integer)
6554                 r_refdef.scene.numentities = 0;
6555
6556         R_AnimCache_ClearCache();
6557         R_FrameData_NewFrame();
6558
6559         /* adjust for stereo display */
6560         if(R_Stereo_Active())
6561         {
6562                 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);
6563                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6564         }
6565
6566         if (r_refdef.view.isoverlay)
6567         {
6568                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6569                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6570                 R_TimeReport("depthclear");
6571
6572                 r_refdef.view.showdebug = false;
6573
6574                 r_waterstate.enabled = false;
6575                 r_waterstate.numwaterplanes = 0;
6576
6577                 R_RenderScene();
6578
6579                 r_refdef.view.matrix = originalmatrix;
6580
6581                 CHECKGLERROR
6582                 return;
6583         }
6584
6585         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6586         {
6587                 r_refdef.view.matrix = originalmatrix;
6588                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6589         }
6590
6591         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6592
6593         R_RenderView_UpdateViewVectors();
6594
6595         R_Shadow_UpdateWorldLightSelection();
6596
6597         R_Bloom_StartFrame();
6598         R_Water_StartFrame();
6599
6600         CHECKGLERROR
6601         if (r_timereport_active)
6602                 R_TimeReport("viewsetup");
6603
6604         R_ResetViewRendering3D();
6605
6606         if (r_refdef.view.clear || r_refdef.fogenabled)
6607         {
6608                 R_ClearScreen(r_refdef.fogenabled);
6609                 if (r_timereport_active)
6610                         R_TimeReport("viewclear");
6611         }
6612         r_refdef.view.clear = true;
6613
6614         // this produces a bloom texture to be used in R_BlendView() later
6615         if (r_bloomstate.hdr)
6616         {
6617                 R_HDR_RenderBloomTexture();
6618                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6619                 r_textureframe++; // used only by R_GetCurrentTexture
6620         }
6621
6622         r_refdef.view.showdebug = true;
6623
6624         R_View_Update();
6625         if (r_timereport_active)
6626                 R_TimeReport("visibility");
6627
6628         r_waterstate.numwaterplanes = 0;
6629         if (r_waterstate.enabled)
6630                 R_RenderWaterPlanes();
6631
6632         R_RenderScene();
6633         r_waterstate.numwaterplanes = 0;
6634
6635         R_BlendView();
6636         if (r_timereport_active)
6637                 R_TimeReport("blendview");
6638
6639         GL_Scissor(0, 0, vid.width, vid.height);
6640         GL_ScissorTest(false);
6641
6642         r_refdef.view.matrix = originalmatrix;
6643
6644         CHECKGLERROR
6645 }
6646
6647 void R_RenderWaterPlanes(void)
6648 {
6649         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6650         {
6651                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6652                 if (r_timereport_active)
6653                         R_TimeReport("waterworld");
6654         }
6655
6656         // don't let sound skip if going slow
6657         if (r_refdef.scene.extraupdate)
6658                 S_ExtraUpdate ();
6659
6660         R_DrawModelsAddWaterPlanes();
6661         if (r_timereport_active)
6662                 R_TimeReport("watermodels");
6663
6664         if (r_waterstate.numwaterplanes)
6665         {
6666                 R_Water_ProcessPlanes();
6667                 if (r_timereport_active)
6668                         R_TimeReport("waterscenes");
6669         }
6670 }
6671
6672 extern void R_DrawLightningBeams (void);
6673 extern void VM_CL_AddPolygonsToMeshQueue (void);
6674 extern void R_DrawPortals (void);
6675 extern cvar_t cl_locs_show;
6676 static void R_DrawLocs(void);
6677 static void R_DrawEntityBBoxes(void);
6678 static void R_DrawModelDecals(void);
6679 extern void R_DrawModelShadows(void);
6680 extern void R_DrawModelShadowMaps(void);
6681 extern cvar_t cl_decals_newsystem;
6682 extern qboolean r_shadow_usingdeferredprepass;
6683 void R_RenderScene(void)
6684 {
6685         qboolean shadowmapping = false;
6686
6687         if (r_timereport_active)
6688                 R_TimeReport("beginscene");
6689
6690         r_refdef.stats.renders++;
6691
6692         R_UpdateFogColor();
6693
6694         // don't let sound skip if going slow
6695         if (r_refdef.scene.extraupdate)
6696                 S_ExtraUpdate ();
6697
6698         R_MeshQueue_BeginScene();
6699
6700         R_SkyStartFrame();
6701
6702         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);
6703
6704         if (r_timereport_active)
6705                 R_TimeReport("skystartframe");
6706
6707         if (cl.csqc_vidvars.drawworld)
6708         {
6709                 // don't let sound skip if going slow
6710                 if (r_refdef.scene.extraupdate)
6711                         S_ExtraUpdate ();
6712
6713                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6714                 {
6715                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6716                         if (r_timereport_active)
6717                                 R_TimeReport("worldsky");
6718                 }
6719
6720                 if (R_DrawBrushModelsSky() && r_timereport_active)
6721                         R_TimeReport("bmodelsky");
6722
6723                 if (skyrendermasked && skyrenderlater)
6724                 {
6725                         // we have to force off the water clipping plane while rendering sky
6726                         R_SetupView(false);
6727                         R_Sky();
6728                         R_SetupView(true);
6729                         if (r_timereport_active)
6730                                 R_TimeReport("sky");
6731                 }
6732         }
6733
6734         R_AnimCache_CacheVisibleEntities();
6735         if (r_timereport_active)
6736                 R_TimeReport("animation");
6737
6738         R_Shadow_PrepareLights();
6739         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6740                 R_Shadow_PrepareModelShadows();
6741         if (r_timereport_active)
6742                 R_TimeReport("preparelights");
6743
6744         if (R_Shadow_ShadowMappingEnabled())
6745                 shadowmapping = true;
6746
6747         if (r_shadow_usingdeferredprepass)
6748                 R_Shadow_DrawPrepass();
6749
6750         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6751         {
6752                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6753                 if (r_timereport_active)
6754                         R_TimeReport("worlddepth");
6755         }
6756         if (r_depthfirst.integer >= 2)
6757         {
6758                 R_DrawModelsDepth();
6759                 if (r_timereport_active)
6760                         R_TimeReport("modeldepth");
6761         }
6762
6763         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6764         {
6765                 R_DrawModelShadowMaps();
6766                 R_ResetViewRendering3D();
6767                 // don't let sound skip if going slow
6768                 if (r_refdef.scene.extraupdate)
6769                         S_ExtraUpdate ();
6770         }
6771
6772         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6773         {
6774                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6775                 if (r_timereport_active)
6776                         R_TimeReport("world");
6777         }
6778
6779         // don't let sound skip if going slow
6780         if (r_refdef.scene.extraupdate)
6781                 S_ExtraUpdate ();
6782
6783         R_DrawModels();
6784         if (r_timereport_active)
6785                 R_TimeReport("models");
6786
6787         // don't let sound skip if going slow
6788         if (r_refdef.scene.extraupdate)
6789                 S_ExtraUpdate ();
6790
6791         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6792         {
6793                 R_DrawModelShadows();
6794                 R_ResetViewRendering3D();
6795                 // don't let sound skip if going slow
6796                 if (r_refdef.scene.extraupdate)
6797                         S_ExtraUpdate ();
6798         }
6799
6800         if (!r_shadow_usingdeferredprepass)
6801         {
6802                 R_Shadow_DrawLights();
6803                 if (r_timereport_active)
6804                         R_TimeReport("rtlights");
6805         }
6806
6807         // don't let sound skip if going slow
6808         if (r_refdef.scene.extraupdate)
6809                 S_ExtraUpdate ();
6810
6811         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6812         {
6813                 R_DrawModelShadows();
6814                 R_ResetViewRendering3D();
6815                 // don't let sound skip if going slow
6816                 if (r_refdef.scene.extraupdate)
6817                         S_ExtraUpdate ();
6818         }
6819
6820         if (cl.csqc_vidvars.drawworld)
6821         {
6822                 if (cl_decals_newsystem.integer)
6823                 {
6824                         R_DrawModelDecals();
6825                         if (r_timereport_active)
6826                                 R_TimeReport("modeldecals");
6827                 }
6828                 else
6829                 {
6830                         R_DrawDecals();
6831                         if (r_timereport_active)
6832                                 R_TimeReport("decals");
6833                 }
6834
6835                 R_DrawParticles();
6836                 if (r_timereport_active)
6837                         R_TimeReport("particles");
6838
6839                 R_DrawExplosions();
6840                 if (r_timereport_active)
6841                         R_TimeReport("explosions");
6842
6843                 R_DrawLightningBeams();
6844                 if (r_timereport_active)
6845                         R_TimeReport("lightning");
6846         }
6847
6848         VM_CL_AddPolygonsToMeshQueue();
6849
6850         if (r_refdef.view.showdebug)
6851         {
6852                 if (cl_locs_show.integer)
6853                 {
6854                         R_DrawLocs();
6855                         if (r_timereport_active)
6856                                 R_TimeReport("showlocs");
6857                 }
6858
6859                 if (r_drawportals.integer)
6860                 {
6861                         R_DrawPortals();
6862                         if (r_timereport_active)
6863                                 R_TimeReport("portals");
6864                 }
6865
6866                 if (r_showbboxes.value > 0)
6867                 {
6868                         R_DrawEntityBBoxes();
6869                         if (r_timereport_active)
6870                                 R_TimeReport("bboxes");
6871                 }
6872         }
6873
6874         if (r_transparent.integer)
6875         {
6876                 R_MeshQueue_RenderTransparent();
6877                 if (r_timereport_active)
6878                         R_TimeReport("drawtrans");
6879         }
6880
6881         if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0 || r_showoverdraw.value > 0))
6882         {
6883                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6884                 if (r_timereport_active)
6885                         R_TimeReport("worlddebug");
6886                 R_DrawModelsDebug();
6887                 if (r_timereport_active)
6888                         R_TimeReport("modeldebug");
6889         }
6890
6891         if (cl.csqc_vidvars.drawworld)
6892         {
6893                 R_Shadow_DrawCoronas();
6894                 if (r_timereport_active)
6895                         R_TimeReport("coronas");
6896         }
6897
6898 #if 0
6899         {
6900                 GL_DepthTest(false);
6901                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6902                 GL_Color(1, 1, 1, 1);
6903                 qglBegin(GL_POLYGON);
6904                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6905                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6906                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6907                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6908                 qglEnd();
6909                 qglBegin(GL_POLYGON);
6910                 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]);
6911                 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]);
6912                 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]);
6913                 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]);
6914                 qglEnd();
6915                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6916         }
6917 #endif
6918
6919         // don't let sound skip if going slow
6920         if (r_refdef.scene.extraupdate)
6921                 S_ExtraUpdate ();
6922
6923         R_ResetViewRendering2D();
6924 }
6925
6926 static const unsigned short bboxelements[36] =
6927 {
6928         5, 1, 3, 5, 3, 7,
6929         6, 2, 0, 6, 0, 4,
6930         7, 3, 2, 7, 2, 6,
6931         4, 0, 1, 4, 1, 5,
6932         4, 5, 7, 4, 7, 6,
6933         1, 0, 2, 1, 2, 3,
6934 };
6935
6936 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6937 {
6938         int i;
6939         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6940
6941         RSurf_ActiveWorldEntity();
6942
6943         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6944         GL_DepthMask(false);
6945         GL_DepthRange(0, 1);
6946         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6947 //      R_Mesh_ResetTextureState();
6948
6949         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6950         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6951         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6952         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6953         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6954         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6955         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6956         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6957         R_FillColors(color4f, 8, cr, cg, cb, ca);
6958         if (r_refdef.fogenabled)
6959         {
6960                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6961                 {
6962                         f1 = RSurf_FogVertex(v);
6963                         f2 = 1 - f1;
6964                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6965                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6966                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6967                 }
6968         }
6969         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6970         R_Mesh_ResetTextureState();
6971         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6972         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6973 }
6974
6975 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6976 {
6977         int i;
6978         float color[4];
6979         prvm_edict_t *edict;
6980         prvm_prog_t *prog_save = prog;
6981
6982         // this function draws bounding boxes of server entities
6983         if (!sv.active)
6984                 return;
6985
6986         GL_CullFace(GL_NONE);
6987         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6988
6989         prog = 0;
6990         SV_VM_Begin();
6991         for (i = 0;i < numsurfaces;i++)
6992         {
6993                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6994                 switch ((int)edict->fields.server->solid)
6995                 {
6996                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6997                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6998                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6999                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7000                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7001                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7002                 }
7003                 color[3] *= r_showbboxes.value;
7004                 color[3] = bound(0, color[3], 1);
7005                 GL_DepthTest(!r_showdisabledepthtest.integer);
7006                 GL_CullFace(r_refdef.view.cullface_front);
7007                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7008         }
7009         SV_VM_End();
7010         prog = prog_save;
7011 }
7012
7013 static void R_DrawEntityBBoxes(void)
7014 {
7015         int i;
7016         prvm_edict_t *edict;
7017         vec3_t center;
7018         prvm_prog_t *prog_save = prog;
7019
7020         // this function draws bounding boxes of server entities
7021         if (!sv.active)
7022                 return;
7023
7024         prog = 0;
7025         SV_VM_Begin();
7026         for (i = 0;i < prog->num_edicts;i++)
7027         {
7028                 edict = PRVM_EDICT_NUM(i);
7029                 if (edict->priv.server->free)
7030                         continue;
7031                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7032                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7033                         continue;
7034                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7035                         continue;
7036                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7037                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7038         }
7039         SV_VM_End();
7040         prog = prog_save;
7041 }
7042
7043 static const int nomodelelement3i[24] =
7044 {
7045         5, 2, 0,
7046         5, 1, 2,
7047         5, 0, 3,
7048         5, 3, 1,
7049         0, 2, 4,
7050         2, 1, 4,
7051         3, 0, 4,
7052         1, 3, 4
7053 };
7054
7055 static const unsigned short nomodelelement3s[24] =
7056 {
7057         5, 2, 0,
7058         5, 1, 2,
7059         5, 0, 3,
7060         5, 3, 1,
7061         0, 2, 4,
7062         2, 1, 4,
7063         3, 0, 4,
7064         1, 3, 4
7065 };
7066
7067 static const float nomodelvertex3f[6*3] =
7068 {
7069         -16,   0,   0,
7070          16,   0,   0,
7071           0, -16,   0,
7072           0,  16,   0,
7073           0,   0, -16,
7074           0,   0,  16
7075 };
7076
7077 static const float nomodelcolor4f[6*4] =
7078 {
7079         0.0f, 0.0f, 0.5f, 1.0f,
7080         0.0f, 0.0f, 0.5f, 1.0f,
7081         0.0f, 0.5f, 0.0f, 1.0f,
7082         0.0f, 0.5f, 0.0f, 1.0f,
7083         0.5f, 0.0f, 0.0f, 1.0f,
7084         0.5f, 0.0f, 0.0f, 1.0f
7085 };
7086
7087 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7088 {
7089         int i;
7090         float f1, f2, *c;
7091         float color4f[6*4];
7092
7093         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);
7094
7095         // this is only called once per entity so numsurfaces is always 1, and
7096         // surfacelist is always {0}, so this code does not handle batches
7097
7098         if (rsurface.ent_flags & RENDER_ADDITIVE)
7099         {
7100                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7101                 GL_DepthMask(false);
7102         }
7103         else if (rsurface.colormod[3] < 1)
7104         {
7105                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7106                 GL_DepthMask(false);
7107         }
7108         else
7109         {
7110                 GL_BlendFunc(GL_ONE, GL_ZERO);
7111                 GL_DepthMask(true);
7112         }
7113         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7114         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7115         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7116         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7117         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7118         for (i = 0, c = color4f;i < 6;i++, c += 4)
7119         {
7120                 c[0] *= rsurface.colormod[0];
7121                 c[1] *= rsurface.colormod[1];
7122                 c[2] *= rsurface.colormod[2];
7123                 c[3] *= rsurface.colormod[3];
7124         }
7125         if (r_refdef.fogenabled)
7126         {
7127                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7128                 {
7129                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7130                         f2 = 1 - f1;
7131                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7132                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7133                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7134                 }
7135         }
7136 //      R_Mesh_ResetTextureState();
7137         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7138         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7139         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7140 }
7141
7142 void R_DrawNoModel(entity_render_t *ent)
7143 {
7144         vec3_t org;
7145         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7146         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7147                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7148         else
7149                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7150 }
7151
7152 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7153 {
7154         vec3_t right1, right2, diff, normal;
7155
7156         VectorSubtract (org2, org1, normal);
7157
7158         // calculate 'right' vector for start
7159         VectorSubtract (r_refdef.view.origin, org1, diff);
7160         CrossProduct (normal, diff, right1);
7161         VectorNormalize (right1);
7162
7163         // calculate 'right' vector for end
7164         VectorSubtract (r_refdef.view.origin, org2, diff);
7165         CrossProduct (normal, diff, right2);
7166         VectorNormalize (right2);
7167
7168         vert[ 0] = org1[0] + width * right1[0];
7169         vert[ 1] = org1[1] + width * right1[1];
7170         vert[ 2] = org1[2] + width * right1[2];
7171         vert[ 3] = org1[0] - width * right1[0];
7172         vert[ 4] = org1[1] - width * right1[1];
7173         vert[ 5] = org1[2] - width * right1[2];
7174         vert[ 6] = org2[0] - width * right2[0];
7175         vert[ 7] = org2[1] - width * right2[1];
7176         vert[ 8] = org2[2] - width * right2[2];
7177         vert[ 9] = org2[0] + width * right2[0];
7178         vert[10] = org2[1] + width * right2[1];
7179         vert[11] = org2[2] + width * right2[2];
7180 }
7181
7182 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)
7183 {
7184         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7185         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7186         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7187         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7188         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7189         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7190         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7191         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7192         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7193         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7194         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7195         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7196 }
7197
7198 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7199 {
7200         int i;
7201         float *vertex3f;
7202         float v[3];
7203         VectorSet(v, x, y, z);
7204         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7205                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7206                         break;
7207         if (i == mesh->numvertices)
7208         {
7209                 if (mesh->numvertices < mesh->maxvertices)
7210                 {
7211                         VectorCopy(v, vertex3f);
7212                         mesh->numvertices++;
7213                 }
7214                 return mesh->numvertices;
7215         }
7216         else
7217                 return i;
7218 }
7219
7220 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7221 {
7222         int i;
7223         int *e, element[3];
7224         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7225         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7226         e = mesh->element3i + mesh->numtriangles * 3;
7227         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7228         {
7229                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7230                 if (mesh->numtriangles < mesh->maxtriangles)
7231                 {
7232                         *e++ = element[0];
7233                         *e++ = element[1];
7234                         *e++ = element[2];
7235                         mesh->numtriangles++;
7236                 }
7237                 element[1] = element[2];
7238         }
7239 }
7240
7241 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7242 {
7243         int i;
7244         int *e, element[3];
7245         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7246         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7247         e = mesh->element3i + mesh->numtriangles * 3;
7248         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7249         {
7250                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7251                 if (mesh->numtriangles < mesh->maxtriangles)
7252                 {
7253                         *e++ = element[0];
7254                         *e++ = element[1];
7255                         *e++ = element[2];
7256                         mesh->numtriangles++;
7257                 }
7258                 element[1] = element[2];
7259         }
7260 }
7261
7262 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7263 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7264 {
7265         int planenum, planenum2;
7266         int w;
7267         int tempnumpoints;
7268         mplane_t *plane, *plane2;
7269         double maxdist;
7270         double temppoints[2][256*3];
7271         // figure out how large a bounding box we need to properly compute this brush
7272         maxdist = 0;
7273         for (w = 0;w < numplanes;w++)
7274                 maxdist = max(maxdist, fabs(planes[w].dist));
7275         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7276         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7277         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7278         {
7279                 w = 0;
7280                 tempnumpoints = 4;
7281                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7282                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7283                 {
7284                         if (planenum2 == planenum)
7285                                 continue;
7286                         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);
7287                         w = !w;
7288                 }
7289                 if (tempnumpoints < 3)
7290                         continue;
7291                 // generate elements forming a triangle fan for this polygon
7292                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7293         }
7294 }
7295
7296 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)
7297 {
7298         texturelayer_t *layer;
7299         layer = t->currentlayers + t->currentnumlayers++;
7300         layer->type = type;
7301         layer->depthmask = depthmask;
7302         layer->blendfunc1 = blendfunc1;
7303         layer->blendfunc2 = blendfunc2;
7304         layer->texture = texture;
7305         layer->texmatrix = *matrix;
7306         layer->color[0] = r;
7307         layer->color[1] = g;
7308         layer->color[2] = b;
7309         layer->color[3] = a;
7310 }
7311
7312 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7313 {
7314         if(parms[0] == 0 && parms[1] == 0)
7315                 return false;
7316         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7317                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7318                         return false;
7319         return true;
7320 }
7321
7322 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7323 {
7324         double index, f;
7325         index = parms[2] + r_refdef.scene.time * parms[3];
7326         index -= floor(index);
7327         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7328         {
7329         default:
7330         case Q3WAVEFUNC_NONE:
7331         case Q3WAVEFUNC_NOISE:
7332         case Q3WAVEFUNC_COUNT:
7333                 f = 0;
7334                 break;
7335         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7336         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7337         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7338         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7339         case Q3WAVEFUNC_TRIANGLE:
7340                 index *= 4;
7341                 f = index - floor(index);
7342                 if (index < 1)
7343                         f = f;
7344                 else if (index < 2)
7345                         f = 1 - f;
7346                 else if (index < 3)
7347                         f = -f;
7348                 else
7349                         f = -(1 - f);
7350                 break;
7351         }
7352         f = parms[0] + parms[1] * f;
7353         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7354                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7355         return (float) f;
7356 }
7357
7358 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7359 {
7360         int w, h, idx;
7361         float f;
7362         float tcmat[12];
7363         matrix4x4_t matrix, temp;
7364         switch(tcmod->tcmod)
7365         {
7366                 case Q3TCMOD_COUNT:
7367                 case Q3TCMOD_NONE:
7368                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7369                                 matrix = r_waterscrollmatrix;
7370                         else
7371                                 matrix = identitymatrix;
7372                         break;
7373                 case Q3TCMOD_ENTITYTRANSLATE:
7374                         // this is used in Q3 to allow the gamecode to control texcoord
7375                         // scrolling on the entity, which is not supported in darkplaces yet.
7376                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7377                         break;
7378                 case Q3TCMOD_ROTATE:
7379                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7380                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7381                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7382                         break;
7383                 case Q3TCMOD_SCALE:
7384                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7385                         break;
7386                 case Q3TCMOD_SCROLL:
7387                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7388                         break;
7389                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7390                         w = (int) tcmod->parms[0];
7391                         h = (int) tcmod->parms[1];
7392                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7393                         f = f - floor(f);
7394                         idx = (int) floor(f * w * h);
7395                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7396                         break;
7397                 case Q3TCMOD_STRETCH:
7398                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7399                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7400                         break;
7401                 case Q3TCMOD_TRANSFORM:
7402                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7403                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7404                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7405                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7406                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7407                         break;
7408                 case Q3TCMOD_TURBULENT:
7409                         // this is handled in the RSurf_PrepareVertices function
7410                         matrix = identitymatrix;
7411                         break;
7412         }
7413         temp = *texmatrix;
7414         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7415 }
7416
7417 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7418 {
7419         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7420         char name[MAX_QPATH];
7421         skinframe_t *skinframe;
7422         unsigned char pixels[296*194];
7423         strlcpy(cache->name, skinname, sizeof(cache->name));
7424         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7425         if (developer_loading.integer)
7426                 Con_Printf("loading %s\n", name);
7427         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7428         if (!skinframe || !skinframe->base)
7429         {
7430                 unsigned char *f;
7431                 fs_offset_t filesize;
7432                 skinframe = NULL;
7433                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7434                 if (f)
7435                 {
7436                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7437                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7438                         Mem_Free(f);
7439                 }
7440         }
7441         cache->skinframe = skinframe;
7442 }
7443
7444 texture_t *R_GetCurrentTexture(texture_t *t)
7445 {
7446         int i;
7447         const entity_render_t *ent = rsurface.entity;
7448         dp_model_t *model = ent->model;
7449         q3shaderinfo_layer_tcmod_t *tcmod;
7450
7451         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7452                 return t->currentframe;
7453         t->update_lastrenderframe = r_textureframe;
7454         t->update_lastrenderentity = (void *)ent;
7455
7456         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7457                 t->camera_entity = ent->entitynumber;
7458         else
7459                 t->camera_entity = 0;
7460
7461         // switch to an alternate material if this is a q1bsp animated material
7462         {
7463                 texture_t *texture = t;
7464                 int s = rsurface.ent_skinnum;
7465                 if ((unsigned int)s >= (unsigned int)model->numskins)
7466                         s = 0;
7467                 if (model->skinscenes)
7468                 {
7469                         if (model->skinscenes[s].framecount > 1)
7470                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7471                         else
7472                                 s = model->skinscenes[s].firstframe;
7473                 }
7474                 if (s > 0)
7475                         t = t + s * model->num_surfaces;
7476                 if (t->animated)
7477                 {
7478                         // use an alternate animation if the entity's frame is not 0,
7479                         // and only if the texture has an alternate animation
7480                         if (rsurface.ent_alttextures && t->anim_total[1])
7481                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7482                         else
7483                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7484                 }
7485                 texture->currentframe = t;
7486         }
7487
7488         // update currentskinframe to be a qw skin or animation frame
7489         if (rsurface.ent_qwskin >= 0)
7490         {
7491                 i = rsurface.ent_qwskin;
7492                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7493                 {
7494                         r_qwskincache_size = cl.maxclients;
7495                         if (r_qwskincache)
7496                                 Mem_Free(r_qwskincache);
7497                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7498                 }
7499                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7500                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7501                 t->currentskinframe = r_qwskincache[i].skinframe;
7502                 if (t->currentskinframe == NULL)
7503                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7504         }
7505         else if (t->numskinframes >= 2)
7506                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7507         if (t->backgroundnumskinframes >= 2)
7508                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7509
7510         t->currentmaterialflags = t->basematerialflags;
7511         t->currentalpha = rsurface.colormod[3];
7512         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7513                 t->currentalpha *= r_wateralpha.value;
7514         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7515                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7516         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7517                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7518         if (!(rsurface.ent_flags & RENDER_LIGHT))
7519                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7520         else if (FAKELIGHT_ENABLED)
7521         {
7522                 // no modellight if using fakelight for the map
7523         }
7524         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7525         {
7526                 // pick a model lighting mode
7527                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7528                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7529                 else
7530                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7531         }
7532         if (rsurface.ent_flags & RENDER_ADDITIVE)
7533                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7534         else if (t->currentalpha < 1)
7535                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7536         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7537                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7538         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7539                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7540         if (t->backgroundnumskinframes)
7541                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7542         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7543         {
7544                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7545                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7546         }
7547         else
7548                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7549         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7550                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7551
7552         // there is no tcmod
7553         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7554         {
7555                 t->currenttexmatrix = r_waterscrollmatrix;
7556                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7557         }
7558         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7559         {
7560                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7561                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7562         }
7563
7564         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7565                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7566         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7567                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7568
7569         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7570         if (t->currentskinframe->qpixels)
7571                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7572         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7573         if (!t->basetexture)
7574                 t->basetexture = r_texture_notexture;
7575         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7576         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7577         t->nmaptexture = t->currentskinframe->nmap;
7578         if (!t->nmaptexture)
7579                 t->nmaptexture = r_texture_blanknormalmap;
7580         t->glosstexture = r_texture_black;
7581         t->glowtexture = t->currentskinframe->glow;
7582         t->fogtexture = t->currentskinframe->fog;
7583         t->reflectmasktexture = t->currentskinframe->reflect;
7584         if (t->backgroundnumskinframes)
7585         {
7586                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7587                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7588                 t->backgroundglosstexture = r_texture_black;
7589                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7590                 if (!t->backgroundnmaptexture)
7591                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7592         }
7593         else
7594         {
7595                 t->backgroundbasetexture = r_texture_white;
7596                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7597                 t->backgroundglosstexture = r_texture_black;
7598                 t->backgroundglowtexture = NULL;
7599         }
7600         t->specularpower = r_shadow_glossexponent.value;
7601         // TODO: store reference values for these in the texture?
7602         t->specularscale = 0;
7603         if (r_shadow_gloss.integer > 0)
7604         {
7605                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7606                 {
7607                         if (r_shadow_glossintensity.value > 0)
7608                         {
7609                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7610                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7611                                 t->specularscale = r_shadow_glossintensity.value;
7612                         }
7613                 }
7614                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7615                 {
7616                         t->glosstexture = r_texture_white;
7617                         t->backgroundglosstexture = r_texture_white;
7618                         t->specularscale = r_shadow_gloss2intensity.value;
7619                         t->specularpower = r_shadow_gloss2exponent.value;
7620                 }
7621         }
7622         t->specularscale *= t->specularscalemod;
7623         t->specularpower *= t->specularpowermod;
7624
7625         // lightmaps mode looks bad with dlights using actual texturing, so turn
7626         // off the colormap and glossmap, but leave the normalmap on as it still
7627         // accurately represents the shading involved
7628         if (gl_lightmaps.integer)
7629         {
7630                 t->basetexture = r_texture_grey128;
7631                 t->pantstexture = r_texture_black;
7632                 t->shirttexture = r_texture_black;
7633                 t->nmaptexture = r_texture_blanknormalmap;
7634                 t->glosstexture = r_texture_black;
7635                 t->glowtexture = NULL;
7636                 t->fogtexture = NULL;
7637                 t->reflectmasktexture = NULL;
7638                 t->backgroundbasetexture = NULL;
7639                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7640                 t->backgroundglosstexture = r_texture_black;
7641                 t->backgroundglowtexture = NULL;
7642                 t->specularscale = 0;
7643                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7644         }
7645
7646         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7647         VectorClear(t->dlightcolor);
7648         t->currentnumlayers = 0;
7649         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7650         {
7651                 int blendfunc1, blendfunc2;
7652                 qboolean depthmask;
7653                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7654                 {
7655                         blendfunc1 = GL_SRC_ALPHA;
7656                         blendfunc2 = GL_ONE;
7657                 }
7658                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7659                 {
7660                         blendfunc1 = GL_SRC_ALPHA;
7661                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7662                 }
7663                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7664                 {
7665                         blendfunc1 = t->customblendfunc[0];
7666                         blendfunc2 = t->customblendfunc[1];
7667                 }
7668                 else
7669                 {
7670                         blendfunc1 = GL_ONE;
7671                         blendfunc2 = GL_ZERO;
7672                 }
7673                 // don't colormod evilblend textures
7674                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7675                         VectorSet(t->lightmapcolor, 1, 1, 1);
7676                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7677                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7678                 {
7679                         // fullbright is not affected by r_refdef.lightmapintensity
7680                         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]);
7681                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7682                                 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]);
7683                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7684                                 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]);
7685                 }
7686                 else
7687                 {
7688                         vec3_t ambientcolor;
7689                         float colorscale;
7690                         // set the color tint used for lights affecting this surface
7691                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7692                         colorscale = 2;
7693                         // q3bsp has no lightmap updates, so the lightstylevalue that
7694                         // would normally be baked into the lightmap must be
7695                         // applied to the color
7696                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7697                         if (model->type == mod_brushq3)
7698                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7699                         colorscale *= r_refdef.lightmapintensity;
7700                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7701                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7702                         // basic lit geometry
7703                         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]);
7704                         // add pants/shirt if needed
7705                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7706                                 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]);
7707                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7708                                 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]);
7709                         // now add ambient passes if needed
7710                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7711                         {
7712                                 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]);
7713                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7714                                         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]);
7715                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7716                                         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]);
7717                         }
7718                 }
7719                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7720                         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]);
7721                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7722                 {
7723                         // if this is opaque use alpha blend which will darken the earlier
7724                         // passes cheaply.
7725                         //
7726                         // if this is an alpha blended material, all the earlier passes
7727                         // were darkened by fog already, so we only need to add the fog
7728                         // color ontop through the fog mask texture
7729                         //
7730                         // if this is an additive blended material, all the earlier passes
7731                         // were darkened by fog already, and we should not add fog color
7732                         // (because the background was not darkened, there is no fog color
7733                         // that was lost behind it).
7734                         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]);
7735                 }
7736         }
7737
7738         return t->currentframe;
7739 }
7740
7741 rsurfacestate_t rsurface;
7742
7743 void RSurf_ActiveWorldEntity(void)
7744 {
7745         dp_model_t *model = r_refdef.scene.worldmodel;
7746         //if (rsurface.entity == r_refdef.scene.worldentity)
7747         //      return;
7748         rsurface.entity = r_refdef.scene.worldentity;
7749         rsurface.skeleton = NULL;
7750         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7751         rsurface.ent_skinnum = 0;
7752         rsurface.ent_qwskin = -1;
7753         rsurface.ent_shadertime = 0;
7754         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7755         rsurface.matrix = identitymatrix;
7756         rsurface.inversematrix = identitymatrix;
7757         rsurface.matrixscale = 1;
7758         rsurface.inversematrixscale = 1;
7759         R_EntityMatrix(&identitymatrix);
7760         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7761         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7762         rsurface.fograngerecip = r_refdef.fograngerecip;
7763         rsurface.fogheightfade = r_refdef.fogheightfade;
7764         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7765         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7766         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7767         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7768         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7769         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7770         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7771         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7772         rsurface.colormod[3] = 1;
7773         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);
7774         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7775         rsurface.frameblend[0].lerp = 1;
7776         rsurface.ent_alttextures = false;
7777         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7778         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7779         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7780         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7781         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7782         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7783         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7784         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7785         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7786         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7787         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7788         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7789         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7790         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7791         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7792         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7793         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7794         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7795         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7796         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7797         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7798         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7799         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7800         rsurface.modelelement3i = model->surfmesh.data_element3i;
7801         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7802         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7803         rsurface.modelelement3s = model->surfmesh.data_element3s;
7804         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7805         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7806         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7807         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7808         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7809         rsurface.modelsurfaces = model->data_surfaces;
7810         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7811         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7812         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7813         rsurface.modelgeneratedvertex = false;
7814         rsurface.batchgeneratedvertex = false;
7815         rsurface.batchfirstvertex = 0;
7816         rsurface.batchnumvertices = 0;
7817         rsurface.batchfirsttriangle = 0;
7818         rsurface.batchnumtriangles = 0;
7819         rsurface.batchvertex3f  = NULL;
7820         rsurface.batchvertex3f_vertexbuffer = NULL;
7821         rsurface.batchvertex3f_bufferoffset = 0;
7822         rsurface.batchsvector3f = NULL;
7823         rsurface.batchsvector3f_vertexbuffer = NULL;
7824         rsurface.batchsvector3f_bufferoffset = 0;
7825         rsurface.batchtvector3f = NULL;
7826         rsurface.batchtvector3f_vertexbuffer = NULL;
7827         rsurface.batchtvector3f_bufferoffset = 0;
7828         rsurface.batchnormal3f  = NULL;
7829         rsurface.batchnormal3f_vertexbuffer = NULL;
7830         rsurface.batchnormal3f_bufferoffset = 0;
7831         rsurface.batchlightmapcolor4f = NULL;
7832         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7833         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7834         rsurface.batchtexcoordtexture2f = NULL;
7835         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7836         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7837         rsurface.batchtexcoordlightmap2f = NULL;
7838         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7839         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7840         rsurface.batchvertexmesh = NULL;
7841         rsurface.batchvertexmeshbuffer = NULL;
7842         rsurface.batchvertex3fbuffer = NULL;
7843         rsurface.batchelement3i = NULL;
7844         rsurface.batchelement3i_indexbuffer = NULL;
7845         rsurface.batchelement3i_bufferoffset = 0;
7846         rsurface.batchelement3s = NULL;
7847         rsurface.batchelement3s_indexbuffer = NULL;
7848         rsurface.batchelement3s_bufferoffset = 0;
7849         rsurface.passcolor4f = NULL;
7850         rsurface.passcolor4f_vertexbuffer = NULL;
7851         rsurface.passcolor4f_bufferoffset = 0;
7852 }
7853
7854 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7855 {
7856         dp_model_t *model = ent->model;
7857         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7858         //      return;
7859         rsurface.entity = (entity_render_t *)ent;
7860         rsurface.skeleton = ent->skeleton;
7861         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7862         rsurface.ent_skinnum = ent->skinnum;
7863         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;
7864         rsurface.ent_shadertime = ent->shadertime;
7865         rsurface.ent_flags = ent->flags;
7866         rsurface.matrix = ent->matrix;
7867         rsurface.inversematrix = ent->inversematrix;
7868         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7869         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7870         R_EntityMatrix(&rsurface.matrix);
7871         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7872         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7873         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7874         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7875         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7876         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7877         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7878         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7879         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7880         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7881         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7882         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7883         rsurface.colormod[3] = ent->alpha;
7884         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7885         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7886         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7887         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7888         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7889         if (ent->model->brush.submodel && !prepass)
7890         {
7891                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7892                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7893         }
7894         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7895         {
7896                 if (ent->animcache_vertex3f)
7897                 {
7898                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7899                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7900                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7901                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7902                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7903                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7904                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7905                 }
7906                 else if (wanttangents)
7907                 {
7908                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7909                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7910                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7911                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7912                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7913                         rsurface.modelvertexmesh = NULL;
7914                         rsurface.modelvertexmeshbuffer = NULL;
7915                         rsurface.modelvertex3fbuffer = NULL;
7916                 }
7917                 else if (wantnormals)
7918                 {
7919                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7920                         rsurface.modelsvector3f = NULL;
7921                         rsurface.modeltvector3f = NULL;
7922                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7923                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7924                         rsurface.modelvertexmesh = NULL;
7925                         rsurface.modelvertexmeshbuffer = NULL;
7926                         rsurface.modelvertex3fbuffer = NULL;
7927                 }
7928                 else
7929                 {
7930                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7931                         rsurface.modelsvector3f = NULL;
7932                         rsurface.modeltvector3f = NULL;
7933                         rsurface.modelnormal3f = NULL;
7934                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7935                         rsurface.modelvertexmesh = NULL;
7936                         rsurface.modelvertexmeshbuffer = NULL;
7937                         rsurface.modelvertex3fbuffer = NULL;
7938                 }
7939                 rsurface.modelvertex3f_vertexbuffer = 0;
7940                 rsurface.modelvertex3f_bufferoffset = 0;
7941                 rsurface.modelsvector3f_vertexbuffer = 0;
7942                 rsurface.modelsvector3f_bufferoffset = 0;
7943                 rsurface.modeltvector3f_vertexbuffer = 0;
7944                 rsurface.modeltvector3f_bufferoffset = 0;
7945                 rsurface.modelnormal3f_vertexbuffer = 0;
7946                 rsurface.modelnormal3f_bufferoffset = 0;
7947                 rsurface.modelgeneratedvertex = true;
7948         }
7949         else
7950         {
7951                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7952                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7953                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7954                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7955                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7956                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7957                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7958                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7959                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7960                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7961                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7962                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7963                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7964                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7965                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7966                 rsurface.modelgeneratedvertex = false;
7967         }
7968         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7969         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7970         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7971         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7972         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7973         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7974         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7975         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7976         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7977         rsurface.modelelement3i = model->surfmesh.data_element3i;
7978         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7979         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7980         rsurface.modelelement3s = model->surfmesh.data_element3s;
7981         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7982         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7983         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7984         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7985         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7986         rsurface.modelsurfaces = model->data_surfaces;
7987         rsurface.batchgeneratedvertex = false;
7988         rsurface.batchfirstvertex = 0;
7989         rsurface.batchnumvertices = 0;
7990         rsurface.batchfirsttriangle = 0;
7991         rsurface.batchnumtriangles = 0;
7992         rsurface.batchvertex3f  = NULL;
7993         rsurface.batchvertex3f_vertexbuffer = NULL;
7994         rsurface.batchvertex3f_bufferoffset = 0;
7995         rsurface.batchsvector3f = NULL;
7996         rsurface.batchsvector3f_vertexbuffer = NULL;
7997         rsurface.batchsvector3f_bufferoffset = 0;
7998         rsurface.batchtvector3f = NULL;
7999         rsurface.batchtvector3f_vertexbuffer = NULL;
8000         rsurface.batchtvector3f_bufferoffset = 0;
8001         rsurface.batchnormal3f  = NULL;
8002         rsurface.batchnormal3f_vertexbuffer = NULL;
8003         rsurface.batchnormal3f_bufferoffset = 0;
8004         rsurface.batchlightmapcolor4f = NULL;
8005         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8006         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8007         rsurface.batchtexcoordtexture2f = NULL;
8008         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8009         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8010         rsurface.batchtexcoordlightmap2f = NULL;
8011         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8012         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8013         rsurface.batchvertexmesh = NULL;
8014         rsurface.batchvertexmeshbuffer = NULL;
8015         rsurface.batchvertex3fbuffer = NULL;
8016         rsurface.batchelement3i = NULL;
8017         rsurface.batchelement3i_indexbuffer = NULL;
8018         rsurface.batchelement3i_bufferoffset = 0;
8019         rsurface.batchelement3s = NULL;
8020         rsurface.batchelement3s_indexbuffer = NULL;
8021         rsurface.batchelement3s_bufferoffset = 0;
8022         rsurface.passcolor4f = NULL;
8023         rsurface.passcolor4f_vertexbuffer = NULL;
8024         rsurface.passcolor4f_bufferoffset = 0;
8025 }
8026
8027 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)
8028 {
8029         rsurface.entity = r_refdef.scene.worldentity;
8030         rsurface.skeleton = NULL;
8031         rsurface.ent_skinnum = 0;
8032         rsurface.ent_qwskin = -1;
8033         rsurface.ent_shadertime = shadertime;
8034         rsurface.ent_flags = entflags;
8035         rsurface.modelnumvertices = numvertices;
8036         rsurface.modelnumtriangles = numtriangles;
8037         rsurface.matrix = *matrix;
8038         rsurface.inversematrix = *inversematrix;
8039         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8040         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8041         R_EntityMatrix(&rsurface.matrix);
8042         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8043         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8044         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8045         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8046         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8047         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8048         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8049         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8050         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8051         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8052         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8053         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8054         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);
8055         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8056         rsurface.frameblend[0].lerp = 1;
8057         rsurface.ent_alttextures = false;
8058         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8059         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8060         if (wanttangents)
8061         {
8062                 rsurface.modelvertex3f = (float *)vertex3f;
8063                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8064                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8065                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8066         }
8067         else if (wantnormals)
8068         {
8069                 rsurface.modelvertex3f = (float *)vertex3f;
8070                 rsurface.modelsvector3f = NULL;
8071                 rsurface.modeltvector3f = NULL;
8072                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8073         }
8074         else
8075         {
8076                 rsurface.modelvertex3f = (float *)vertex3f;
8077                 rsurface.modelsvector3f = NULL;
8078                 rsurface.modeltvector3f = NULL;
8079                 rsurface.modelnormal3f = NULL;
8080         }
8081         rsurface.modelvertexmesh = NULL;
8082         rsurface.modelvertexmeshbuffer = NULL;
8083         rsurface.modelvertex3fbuffer = NULL;
8084         rsurface.modelvertex3f_vertexbuffer = 0;
8085         rsurface.modelvertex3f_bufferoffset = 0;
8086         rsurface.modelsvector3f_vertexbuffer = 0;
8087         rsurface.modelsvector3f_bufferoffset = 0;
8088         rsurface.modeltvector3f_vertexbuffer = 0;
8089         rsurface.modeltvector3f_bufferoffset = 0;
8090         rsurface.modelnormal3f_vertexbuffer = 0;
8091         rsurface.modelnormal3f_bufferoffset = 0;
8092         rsurface.modelgeneratedvertex = true;
8093         rsurface.modellightmapcolor4f  = (float *)color4f;
8094         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8095         rsurface.modellightmapcolor4f_bufferoffset = 0;
8096         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8097         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8098         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8099         rsurface.modeltexcoordlightmap2f  = NULL;
8100         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8101         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8102         rsurface.modelelement3i = (int *)element3i;
8103         rsurface.modelelement3i_indexbuffer = NULL;
8104         rsurface.modelelement3i_bufferoffset = 0;
8105         rsurface.modelelement3s = (unsigned short *)element3s;
8106         rsurface.modelelement3s_indexbuffer = NULL;
8107         rsurface.modelelement3s_bufferoffset = 0;
8108         rsurface.modellightmapoffsets = NULL;
8109         rsurface.modelsurfaces = NULL;
8110         rsurface.batchgeneratedvertex = false;
8111         rsurface.batchfirstvertex = 0;
8112         rsurface.batchnumvertices = 0;
8113         rsurface.batchfirsttriangle = 0;
8114         rsurface.batchnumtriangles = 0;
8115         rsurface.batchvertex3f  = NULL;
8116         rsurface.batchvertex3f_vertexbuffer = NULL;
8117         rsurface.batchvertex3f_bufferoffset = 0;
8118         rsurface.batchsvector3f = NULL;
8119         rsurface.batchsvector3f_vertexbuffer = NULL;
8120         rsurface.batchsvector3f_bufferoffset = 0;
8121         rsurface.batchtvector3f = NULL;
8122         rsurface.batchtvector3f_vertexbuffer = NULL;
8123         rsurface.batchtvector3f_bufferoffset = 0;
8124         rsurface.batchnormal3f  = NULL;
8125         rsurface.batchnormal3f_vertexbuffer = NULL;
8126         rsurface.batchnormal3f_bufferoffset = 0;
8127         rsurface.batchlightmapcolor4f = NULL;
8128         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8129         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8130         rsurface.batchtexcoordtexture2f = NULL;
8131         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8132         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8133         rsurface.batchtexcoordlightmap2f = NULL;
8134         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8135         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8136         rsurface.batchvertexmesh = NULL;
8137         rsurface.batchvertexmeshbuffer = NULL;
8138         rsurface.batchvertex3fbuffer = NULL;
8139         rsurface.batchelement3i = NULL;
8140         rsurface.batchelement3i_indexbuffer = NULL;
8141         rsurface.batchelement3i_bufferoffset = 0;
8142         rsurface.batchelement3s = NULL;
8143         rsurface.batchelement3s_indexbuffer = NULL;
8144         rsurface.batchelement3s_bufferoffset = 0;
8145         rsurface.passcolor4f = NULL;
8146         rsurface.passcolor4f_vertexbuffer = NULL;
8147         rsurface.passcolor4f_bufferoffset = 0;
8148
8149         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8150         {
8151                 if ((wantnormals || wanttangents) && !normal3f)
8152                 {
8153                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8154                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8155                 }
8156                 if (wanttangents && !svector3f)
8157                 {
8158                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8159                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8160                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8161                 }
8162         }
8163 }
8164
8165 float RSurf_FogPoint(const float *v)
8166 {
8167         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8168         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8169         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8170         float FogHeightFade = r_refdef.fogheightfade;
8171         float fogfrac;
8172         unsigned int fogmasktableindex;
8173         if (r_refdef.fogplaneviewabove)
8174                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8175         else
8176                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8177         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8178         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8179 }
8180
8181 float RSurf_FogVertex(const float *v)
8182 {
8183         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8184         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8185         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8186         float FogHeightFade = rsurface.fogheightfade;
8187         float fogfrac;
8188         unsigned int fogmasktableindex;
8189         if (r_refdef.fogplaneviewabove)
8190                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8191         else
8192                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8193         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8194         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8195 }
8196
8197 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8198 {
8199         int i;
8200         for (i = 0;i < numelements;i++)
8201                 outelement3i[i] = inelement3i[i] + adjust;
8202 }
8203
8204 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8205 extern cvar_t gl_vbo;
8206 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8207 {
8208         int deformindex;
8209         int firsttriangle;
8210         int numtriangles;
8211         int firstvertex;
8212         int endvertex;
8213         int numvertices;
8214         int surfacefirsttriangle;
8215         int surfacenumtriangles;
8216         int surfacefirstvertex;
8217         int surfaceendvertex;
8218         int surfacenumvertices;
8219         int batchnumvertices;
8220         int batchnumtriangles;
8221         int needsupdate;
8222         int i, j;
8223         qboolean gaps;
8224         qboolean dynamicvertex;
8225         float amplitude;
8226         float animpos;
8227         float scale;
8228         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8229         float waveparms[4];
8230         q3shaderinfo_deform_t *deform;
8231         const msurface_t *surface, *firstsurface;
8232         r_vertexmesh_t *vertexmesh;
8233         if (!texturenumsurfaces)
8234                 return;
8235         // find vertex range of this surface batch
8236         gaps = false;
8237         firstsurface = texturesurfacelist[0];
8238         firsttriangle = firstsurface->num_firsttriangle;
8239         batchnumvertices = 0;
8240         batchnumtriangles = 0;
8241         firstvertex = endvertex = firstsurface->num_firstvertex;
8242         for (i = 0;i < texturenumsurfaces;i++)
8243         {
8244                 surface = texturesurfacelist[i];
8245                 if (surface != firstsurface + i)
8246                         gaps = true;
8247                 surfacefirstvertex = surface->num_firstvertex;
8248                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8249                 surfacenumvertices = surface->num_vertices;
8250                 surfacenumtriangles = surface->num_triangles;
8251                 if (firstvertex > surfacefirstvertex)
8252                         firstvertex = surfacefirstvertex;
8253                 if (endvertex < surfaceendvertex)
8254                         endvertex = surfaceendvertex;
8255                 batchnumvertices += surfacenumvertices;
8256                 batchnumtriangles += surfacenumtriangles;
8257         }
8258
8259         // we now know the vertex range used, and if there are any gaps in it
8260         rsurface.batchfirstvertex = firstvertex;
8261         rsurface.batchnumvertices = endvertex - firstvertex;
8262         rsurface.batchfirsttriangle = firsttriangle;
8263         rsurface.batchnumtriangles = batchnumtriangles;
8264
8265         // this variable holds flags for which properties have been updated that
8266         // may require regenerating vertexmesh array...
8267         needsupdate = 0;
8268
8269         // check if any dynamic vertex processing must occur
8270         dynamicvertex = false;
8271
8272         // if there is a chance of animated vertex colors, it's a dynamic batch
8273         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8274         {
8275                 dynamicvertex = true;
8276                 batchneed |= BATCHNEED_NOGAPS;
8277                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8278         }
8279
8280         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8281         {
8282                 switch (deform->deform)
8283                 {
8284                 default:
8285                 case Q3DEFORM_PROJECTIONSHADOW:
8286                 case Q3DEFORM_TEXT0:
8287                 case Q3DEFORM_TEXT1:
8288                 case Q3DEFORM_TEXT2:
8289                 case Q3DEFORM_TEXT3:
8290                 case Q3DEFORM_TEXT4:
8291                 case Q3DEFORM_TEXT5:
8292                 case Q3DEFORM_TEXT6:
8293                 case Q3DEFORM_TEXT7:
8294                 case Q3DEFORM_NONE:
8295                         break;
8296                 case Q3DEFORM_AUTOSPRITE:
8297                         dynamicvertex = true;
8298                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8299                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8300                         break;
8301                 case Q3DEFORM_AUTOSPRITE2:
8302                         dynamicvertex = true;
8303                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8304                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8305                         break;
8306                 case Q3DEFORM_NORMAL:
8307                         dynamicvertex = true;
8308                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8309                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8310                         break;
8311                 case Q3DEFORM_WAVE:
8312                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8313                                 break; // if wavefunc is a nop, ignore this transform
8314                         dynamicvertex = true;
8315                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8316                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8317                         break;
8318                 case Q3DEFORM_BULGE:
8319                         dynamicvertex = true;
8320                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8321                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8322                         break;
8323                 case Q3DEFORM_MOVE:
8324                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8325                                 break; // if wavefunc is a nop, ignore this transform
8326                         dynamicvertex = true;
8327                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8328                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8329                         break;
8330                 }
8331         }
8332         switch(rsurface.texture->tcgen.tcgen)
8333         {
8334         default:
8335         case Q3TCGEN_TEXTURE:
8336                 break;
8337         case Q3TCGEN_LIGHTMAP:
8338                 dynamicvertex = true;
8339                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8340                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8341                 break;
8342         case Q3TCGEN_VECTOR:
8343                 dynamicvertex = true;
8344                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8345                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8346                 break;
8347         case Q3TCGEN_ENVIRONMENT:
8348                 dynamicvertex = true;
8349                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8350                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8351                 break;
8352         }
8353         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8354         {
8355                 dynamicvertex = true;
8356                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8357                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8358         }
8359
8360         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8361         {
8362                 dynamicvertex = true;
8363                 batchneed |= BATCHNEED_NOGAPS;
8364                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8365         }
8366
8367         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8368         {
8369                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8370                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8371                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8372                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8373                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8374                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8375                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8376         }
8377
8378         // when the model data has no vertex buffer (dynamic mesh), we need to
8379         // eliminate gaps
8380         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8381                 batchneed |= BATCHNEED_NOGAPS;
8382
8383         // if needsupdate, we have to do a dynamic vertex batch for sure
8384         if (needsupdate & batchneed)
8385                 dynamicvertex = true;
8386
8387         // see if we need to build vertexmesh from arrays
8388         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8389                 dynamicvertex = true;
8390
8391         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8392         // also some drivers strongly dislike firstvertex
8393         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8394                 dynamicvertex = true;
8395
8396         rsurface.batchvertex3f = rsurface.modelvertex3f;
8397         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8398         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8399         rsurface.batchsvector3f = rsurface.modelsvector3f;
8400         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8401         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8402         rsurface.batchtvector3f = rsurface.modeltvector3f;
8403         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8404         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8405         rsurface.batchnormal3f = rsurface.modelnormal3f;
8406         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8407         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8408         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8409         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8410         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8411         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8412         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8413         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8414         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8415         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8416         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8417         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8418         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8419         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8420         rsurface.batchelement3i = rsurface.modelelement3i;
8421         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8422         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8423         rsurface.batchelement3s = rsurface.modelelement3s;
8424         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8425         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8426
8427         // if any dynamic vertex processing has to occur in software, we copy the
8428         // entire surface list together before processing to rebase the vertices
8429         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8430         //
8431         // if any gaps exist and we do not have a static vertex buffer, we have to
8432         // copy the surface list together to avoid wasting upload bandwidth on the
8433         // vertices in the gaps.
8434         //
8435         // if gaps exist and we have a static vertex buffer, we still have to
8436         // combine the index buffer ranges into one dynamic index buffer.
8437         //
8438         // in all cases we end up with data that can be drawn in one call.
8439
8440         if (!dynamicvertex)
8441         {
8442                 // static vertex data, just set pointers...
8443                 rsurface.batchgeneratedvertex = false;
8444                 // if there are gaps, we want to build a combined index buffer,
8445                 // otherwise use the original static buffer with an appropriate offset
8446                 if (gaps)
8447                 {
8448                         // build a new triangle elements array for this batch
8449                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8450                         rsurface.batchfirsttriangle = 0;
8451                         numtriangles = 0;
8452                         for (i = 0;i < texturenumsurfaces;i++)
8453                         {
8454                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8455                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8456                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8457                                 numtriangles += surfacenumtriangles;
8458                         }
8459                         rsurface.batchelement3i_indexbuffer = NULL;
8460                         rsurface.batchelement3i_bufferoffset = 0;
8461                         rsurface.batchelement3s = NULL;
8462                         rsurface.batchelement3s_indexbuffer = NULL;
8463                         rsurface.batchelement3s_bufferoffset = 0;
8464                         if (endvertex <= 65536)
8465                         {
8466                                 // make a 16bit (unsigned short) index array if possible
8467                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8468                                 for (i = 0;i < numtriangles*3;i++)
8469                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8470                         }
8471                 }
8472                 return;
8473         }
8474
8475         // something needs software processing, do it for real...
8476         // we only directly handle separate array data in this case and then
8477         // generate interleaved data if needed...
8478         rsurface.batchgeneratedvertex = true;
8479
8480         // now copy the vertex data into a combined array and make an index array
8481         // (this is what Quake3 does all the time)
8482         //if (gaps || rsurface.batchfirstvertex)
8483         {
8484                 rsurface.batchvertex3fbuffer = NULL;
8485                 rsurface.batchvertexmesh = NULL;
8486                 rsurface.batchvertexmeshbuffer = NULL;
8487                 rsurface.batchvertex3f = NULL;
8488                 rsurface.batchvertex3f_vertexbuffer = NULL;
8489                 rsurface.batchvertex3f_bufferoffset = 0;
8490                 rsurface.batchsvector3f = NULL;
8491                 rsurface.batchsvector3f_vertexbuffer = NULL;
8492                 rsurface.batchsvector3f_bufferoffset = 0;
8493                 rsurface.batchtvector3f = NULL;
8494                 rsurface.batchtvector3f_vertexbuffer = NULL;
8495                 rsurface.batchtvector3f_bufferoffset = 0;
8496                 rsurface.batchnormal3f = NULL;
8497                 rsurface.batchnormal3f_vertexbuffer = NULL;
8498                 rsurface.batchnormal3f_bufferoffset = 0;
8499                 rsurface.batchlightmapcolor4f = NULL;
8500                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8501                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8502                 rsurface.batchtexcoordtexture2f = NULL;
8503                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8504                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8505                 rsurface.batchtexcoordlightmap2f = NULL;
8506                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8507                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8508                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8509                 rsurface.batchelement3i_indexbuffer = NULL;
8510                 rsurface.batchelement3i_bufferoffset = 0;
8511                 rsurface.batchelement3s = NULL;
8512                 rsurface.batchelement3s_indexbuffer = NULL;
8513                 rsurface.batchelement3s_bufferoffset = 0;
8514                 // we'll only be setting up certain arrays as needed
8515                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8516                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8517                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8518                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8519                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8520                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8521                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8522                 {
8523                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8524                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8525                 }
8526                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8527                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8528                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8529                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8530                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8531                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8532                 numvertices = 0;
8533                 numtriangles = 0;
8534                 for (i = 0;i < texturenumsurfaces;i++)
8535                 {
8536                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8537                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8538                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8539                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8540                         // copy only the data requested
8541                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8542                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8543                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8544                         {
8545                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8546                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8547                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8548                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8549                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8550                                 {
8551                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8552                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8553                                 }
8554                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8555                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8556                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8557                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8558                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8559                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8560                         }
8561                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8562                         numvertices += surfacenumvertices;
8563                         numtriangles += surfacenumtriangles;
8564                 }
8565
8566                 // generate a 16bit index array as well if possible
8567                 // (in general, dynamic batches fit)
8568                 if (numvertices <= 65536)
8569                 {
8570                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8571                         for (i = 0;i < numtriangles*3;i++)
8572                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8573                 }
8574
8575                 // since we've copied everything, the batch now starts at 0
8576                 rsurface.batchfirstvertex = 0;
8577                 rsurface.batchnumvertices = batchnumvertices;
8578                 rsurface.batchfirsttriangle = 0;
8579                 rsurface.batchnumtriangles = batchnumtriangles;
8580         }
8581
8582         // q1bsp surfaces rendered in vertex color mode have to have colors
8583         // calculated based on lightstyles
8584         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8585         {
8586                 // generate color arrays for the surfaces in this list
8587                 int c[4];
8588                 int scale;
8589                 int size3;
8590                 const int *offsets;
8591                 const unsigned char *lm;
8592                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8593                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8594                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8595                 numvertices = 0;
8596                 for (i = 0;i < texturenumsurfaces;i++)
8597                 {
8598                         surface = texturesurfacelist[i];
8599                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8600                         surfacenumvertices = surface->num_vertices;
8601                         if (surface->lightmapinfo->samples)
8602                         {
8603                                 for (j = 0;j < surfacenumvertices;j++)
8604                                 {
8605                                         lm = surface->lightmapinfo->samples + offsets[j];
8606                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8607                                         VectorScale(lm, scale, c);
8608                                         if (surface->lightmapinfo->styles[1] != 255)
8609                                         {
8610                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8611                                                 lm += size3;
8612                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8613                                                 VectorMA(c, scale, lm, c);
8614                                                 if (surface->lightmapinfo->styles[2] != 255)
8615                                                 {
8616                                                         lm += size3;
8617                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8618                                                         VectorMA(c, scale, lm, c);
8619                                                         if (surface->lightmapinfo->styles[3] != 255)
8620                                                         {
8621                                                                 lm += size3;
8622                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8623                                                                 VectorMA(c, scale, lm, c);
8624                                                         }
8625                                                 }
8626                                         }
8627                                         c[0] >>= 7;
8628                                         c[1] >>= 7;
8629                                         c[2] >>= 7;
8630                                         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);
8631                                         numvertices++;
8632                                 }
8633                         }
8634                         else
8635                         {
8636                                 for (j = 0;j < surfacenumvertices;j++)
8637                                 {
8638                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8639                                         numvertices++;
8640                                 }
8641                         }
8642                 }
8643         }
8644
8645         // if vertices are deformed (sprite flares and things in maps, possibly
8646         // water waves, bulges and other deformations), modify the copied vertices
8647         // in place
8648         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8649         {
8650                 switch (deform->deform)
8651                 {
8652                 default:
8653                 case Q3DEFORM_PROJECTIONSHADOW:
8654                 case Q3DEFORM_TEXT0:
8655                 case Q3DEFORM_TEXT1:
8656                 case Q3DEFORM_TEXT2:
8657                 case Q3DEFORM_TEXT3:
8658                 case Q3DEFORM_TEXT4:
8659                 case Q3DEFORM_TEXT5:
8660                 case Q3DEFORM_TEXT6:
8661                 case Q3DEFORM_TEXT7:
8662                 case Q3DEFORM_NONE:
8663                         break;
8664                 case Q3DEFORM_AUTOSPRITE:
8665                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8666                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8667                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8668                         VectorNormalize(newforward);
8669                         VectorNormalize(newright);
8670                         VectorNormalize(newup);
8671 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8672 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8673 //                      rsurface.batchvertex3f_bufferoffset = 0;
8674 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8675 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8676 //                      rsurface.batchsvector3f_bufferoffset = 0;
8677 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8678 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8679 //                      rsurface.batchtvector3f_bufferoffset = 0;
8680 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8681 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8682 //                      rsurface.batchnormal3f_bufferoffset = 0;
8683                         // a single autosprite surface can contain multiple sprites...
8684                         for (j = 0;j < batchnumvertices - 3;j += 4)
8685                         {
8686                                 VectorClear(center);
8687                                 for (i = 0;i < 4;i++)
8688                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8689                                 VectorScale(center, 0.25f, center);
8690                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8691                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8692                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8693                                 for (i = 0;i < 4;i++)
8694                                 {
8695                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8696                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8697                                 }
8698                         }
8699                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8700                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8701                         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);
8702                         break;
8703                 case Q3DEFORM_AUTOSPRITE2:
8704                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8705                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8706                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8707                         VectorNormalize(newforward);
8708                         VectorNormalize(newright);
8709                         VectorNormalize(newup);
8710 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8711 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8712 //                      rsurface.batchvertex3f_bufferoffset = 0;
8713                         {
8714                                 const float *v1, *v2;
8715                                 vec3_t start, end;
8716                                 float f, l;
8717                                 struct
8718                                 {
8719                                         float length2;
8720                                         const float *v1;
8721                                         const float *v2;
8722                                 }
8723                                 shortest[2];
8724                                 memset(shortest, 0, sizeof(shortest));
8725                                 // a single autosprite surface can contain multiple sprites...
8726                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8727                                 {
8728                                         VectorClear(center);
8729                                         for (i = 0;i < 4;i++)
8730                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8731                                         VectorScale(center, 0.25f, center);
8732                                         // find the two shortest edges, then use them to define the
8733                                         // axis vectors for rotating around the central axis
8734                                         for (i = 0;i < 6;i++)
8735                                         {
8736                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8737                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8738                                                 l = VectorDistance2(v1, v2);
8739                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8740                                                 if (v1[2] != v2[2])
8741                                                         l += (1.0f / 1024.0f);
8742                                                 if (shortest[0].length2 > l || i == 0)
8743                                                 {
8744                                                         shortest[1] = shortest[0];
8745                                                         shortest[0].length2 = l;
8746                                                         shortest[0].v1 = v1;
8747                                                         shortest[0].v2 = v2;
8748                                                 }
8749                                                 else if (shortest[1].length2 > l || i == 1)
8750                                                 {
8751                                                         shortest[1].length2 = l;
8752                                                         shortest[1].v1 = v1;
8753                                                         shortest[1].v2 = v2;
8754                                                 }
8755                                         }
8756                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8757                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8758                                         // this calculates the right vector from the shortest edge
8759                                         // and the up vector from the edge midpoints
8760                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8761                                         VectorNormalize(right);
8762                                         VectorSubtract(end, start, up);
8763                                         VectorNormalize(up);
8764                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8765                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8766                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8767                                         VectorNegate(forward, forward);
8768                                         VectorReflect(forward, 0, up, forward);
8769                                         VectorNormalize(forward);
8770                                         CrossProduct(up, forward, newright);
8771                                         VectorNormalize(newright);
8772                                         // rotate the quad around the up axis vector, this is made
8773                                         // especially easy by the fact we know the quad is flat,
8774                                         // so we only have to subtract the center position and
8775                                         // measure distance along the right vector, and then
8776                                         // multiply that by the newright vector and add back the
8777                                         // center position
8778                                         // we also need to subtract the old position to undo the
8779                                         // displacement from the center, which we do with a
8780                                         // DotProduct, the subtraction/addition of center is also
8781                                         // optimized into DotProducts here
8782                                         l = DotProduct(right, center);
8783                                         for (i = 0;i < 4;i++)
8784                                         {
8785                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8786                                                 f = DotProduct(right, v1) - l;
8787                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8788                                         }
8789                                 }
8790                         }
8791                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8792                         {
8793 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8794 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8795 //                              rsurface.batchnormal3f_bufferoffset = 0;
8796                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8797                         }
8798                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8799                         {
8800 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8801 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8802 //                              rsurface.batchsvector3f_bufferoffset = 0;
8803 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8804 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8805 //                              rsurface.batchtvector3f_bufferoffset = 0;
8806                                 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);
8807                         }
8808                         break;
8809                 case Q3DEFORM_NORMAL:
8810                         // deform the normals to make reflections wavey
8811                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8812                         rsurface.batchnormal3f_vertexbuffer = NULL;
8813                         rsurface.batchnormal3f_bufferoffset = 0;
8814                         for (j = 0;j < batchnumvertices;j++)
8815                         {
8816                                 float vertex[3];
8817                                 float *normal = rsurface.batchnormal3f + 3*j;
8818                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8819                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8820                                 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]);
8821                                 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]);
8822                                 VectorNormalize(normal);
8823                         }
8824                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8825                         {
8826 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8827 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8828 //                              rsurface.batchsvector3f_bufferoffset = 0;
8829 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8830 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8831 //                              rsurface.batchtvector3f_bufferoffset = 0;
8832                                 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);
8833                         }
8834                         break;
8835                 case Q3DEFORM_WAVE:
8836                         // deform vertex array to make wavey water and flags and such
8837                         waveparms[0] = deform->waveparms[0];
8838                         waveparms[1] = deform->waveparms[1];
8839                         waveparms[2] = deform->waveparms[2];
8840                         waveparms[3] = deform->waveparms[3];
8841                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8842                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8843                         // this is how a divisor of vertex influence on deformation
8844                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8845                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8846 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8847 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8848 //                      rsurface.batchvertex3f_bufferoffset = 0;
8849 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8850 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8851 //                      rsurface.batchnormal3f_bufferoffset = 0;
8852                         for (j = 0;j < batchnumvertices;j++)
8853                         {
8854                                 // if the wavefunc depends on time, evaluate it per-vertex
8855                                 if (waveparms[3])
8856                                 {
8857                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8858                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8859                                 }
8860                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8861                         }
8862                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8863                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8864                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8865                         {
8866 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8867 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8868 //                              rsurface.batchsvector3f_bufferoffset = 0;
8869 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8870 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8871 //                              rsurface.batchtvector3f_bufferoffset = 0;
8872                                 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);
8873                         }
8874                         break;
8875                 case Q3DEFORM_BULGE:
8876                         // deform vertex array to make the surface have moving bulges
8877 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8878 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8879 //                      rsurface.batchvertex3f_bufferoffset = 0;
8880 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8881 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8882 //                      rsurface.batchnormal3f_bufferoffset = 0;
8883                         for (j = 0;j < batchnumvertices;j++)
8884                         {
8885                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8886                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8887                         }
8888                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8889                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8890                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8891                         {
8892 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8893 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8894 //                              rsurface.batchsvector3f_bufferoffset = 0;
8895 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8896 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8897 //                              rsurface.batchtvector3f_bufferoffset = 0;
8898                                 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);
8899                         }
8900                         break;
8901                 case Q3DEFORM_MOVE:
8902                         // deform vertex array
8903                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8904                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8905                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8906                         VectorScale(deform->parms, scale, waveparms);
8907 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8908 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8909 //                      rsurface.batchvertex3f_bufferoffset = 0;
8910                         for (j = 0;j < batchnumvertices;j++)
8911                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8912                         break;
8913                 }
8914         }
8915
8916         // generate texcoords based on the chosen texcoord source
8917         switch(rsurface.texture->tcgen.tcgen)
8918         {
8919         default:
8920         case Q3TCGEN_TEXTURE:
8921                 break;
8922         case Q3TCGEN_LIGHTMAP:
8923 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8924 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8925 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8926                 if (rsurface.batchtexcoordlightmap2f)
8927                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8928                 break;
8929         case Q3TCGEN_VECTOR:
8930 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8931 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8932 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8933                 for (j = 0;j < batchnumvertices;j++)
8934                 {
8935                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8936                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8937                 }
8938                 break;
8939         case Q3TCGEN_ENVIRONMENT:
8940                 // make environment reflections using a spheremap
8941                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8942                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8943                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8944                 for (j = 0;j < batchnumvertices;j++)
8945                 {
8946                         // identical to Q3A's method, but executed in worldspace so
8947                         // carried models can be shiny too
8948
8949                         float viewer[3], d, reflected[3], worldreflected[3];
8950
8951                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8952                         // VectorNormalize(viewer);
8953
8954                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8955
8956                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8957                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8958                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8959                         // note: this is proportinal to viewer, so we can normalize later
8960
8961                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8962                         VectorNormalize(worldreflected);
8963
8964                         // note: this sphere map only uses world x and z!
8965                         // so positive and negative y will LOOK THE SAME.
8966                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8967                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8968                 }
8969                 break;
8970         }
8971         // the only tcmod that needs software vertex processing is turbulent, so
8972         // check for it here and apply the changes if needed
8973         // and we only support that as the first one
8974         // (handling a mixture of turbulent and other tcmods would be problematic
8975         //  without punting it entirely to a software path)
8976         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8977         {
8978                 amplitude = rsurface.texture->tcmods[0].parms[1];
8979                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8980 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8981 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8982 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8983                 for (j = 0;j < batchnumvertices;j++)
8984                 {
8985                         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);
8986                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8987                 }
8988         }
8989
8990         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8991         {
8992                 // convert the modified arrays to vertex structs
8993 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8994 //              rsurface.batchvertexmeshbuffer = NULL;
8995                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8996                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8997                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8998                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8999                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9000                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9001                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9002                 {
9003                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9004                         {
9005                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9006                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9007                         }
9008                 }
9009                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9010                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9011                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9012                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9013                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9014                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9015                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9016                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9017                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9018         }
9019 }
9020
9021 void RSurf_DrawBatch(void)
9022 {
9023         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9024         // through the pipeline, killing it earlier in the pipeline would have
9025         // per-surface overhead rather than per-batch overhead, so it's best to
9026         // reject it here, before it hits glDraw.
9027         if (rsurface.batchnumtriangles == 0)
9028                 return;
9029 #if 0
9030         // batch debugging code
9031         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9032         {
9033                 int i;
9034                 int j;
9035                 int c;
9036                 const int *e;
9037                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9038                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9039                 {
9040                         c = e[i];
9041                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9042                         {
9043                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9044                                 {
9045                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9046                                                 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);
9047                                         break;
9048                                 }
9049                         }
9050                 }
9051         }
9052 #endif
9053         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);
9054 }
9055
9056 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9057 {
9058         // pick the closest matching water plane
9059         int planeindex, vertexindex, bestplaneindex = -1;
9060         float d, bestd;
9061         vec3_t vert;
9062         const float *v;
9063         r_waterstate_waterplane_t *p;
9064         qboolean prepared = false;
9065         bestd = 0;
9066         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9067         {
9068                 if(p->camera_entity != rsurface.texture->camera_entity)
9069                         continue;
9070                 d = 0;
9071                 if(!prepared)
9072                 {
9073                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9074                         prepared = true;
9075                         if(rsurface.batchnumvertices == 0)
9076                                 break;
9077                 }
9078                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9079                 {
9080                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9081                         d += fabs(PlaneDiff(vert, &p->plane));
9082                 }
9083                 if (bestd > d || bestplaneindex < 0)
9084                 {
9085                         bestd = d;
9086                         bestplaneindex = planeindex;
9087                 }
9088         }
9089         return bestplaneindex;
9090         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9091         // this situation though, as it might be better to render single larger
9092         // batches with useless stuff (backface culled for example) than to
9093         // render multiple smaller batches
9094 }
9095
9096 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9097 {
9098         int i;
9099         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9100         rsurface.passcolor4f_vertexbuffer = 0;
9101         rsurface.passcolor4f_bufferoffset = 0;
9102         for (i = 0;i < rsurface.batchnumvertices;i++)
9103                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9104 }
9105
9106 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9107 {
9108         int i;
9109         float f;
9110         const float *v;
9111         const float *c;
9112         float *c2;
9113         if (rsurface.passcolor4f)
9114         {
9115                 // generate color arrays
9116                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9117                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9118                 rsurface.passcolor4f_vertexbuffer = 0;
9119                 rsurface.passcolor4f_bufferoffset = 0;
9120                 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)
9121                 {
9122                         f = RSurf_FogVertex(v);
9123                         c2[0] = c[0] * f;
9124                         c2[1] = c[1] * f;
9125                         c2[2] = c[2] * f;
9126                         c2[3] = c[3];
9127                 }
9128         }
9129         else
9130         {
9131                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9132                 rsurface.passcolor4f_vertexbuffer = 0;
9133                 rsurface.passcolor4f_bufferoffset = 0;
9134                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9135                 {
9136                         f = RSurf_FogVertex(v);
9137                         c2[0] = f;
9138                         c2[1] = f;
9139                         c2[2] = f;
9140                         c2[3] = 1;
9141                 }
9142         }
9143 }
9144
9145 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9146 {
9147         int i;
9148         float f;
9149         const float *v;
9150         const float *c;
9151         float *c2;
9152         if (!rsurface.passcolor4f)
9153                 return;
9154         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9155         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9156         rsurface.passcolor4f_vertexbuffer = 0;
9157         rsurface.passcolor4f_bufferoffset = 0;
9158         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)
9159         {
9160                 f = RSurf_FogVertex(v);
9161                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9162                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9163                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9164                 c2[3] = c[3];
9165         }
9166 }
9167
9168 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9169 {
9170         int i;
9171         const float *c;
9172         float *c2;
9173         if (!rsurface.passcolor4f)
9174                 return;
9175         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9176         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9177         rsurface.passcolor4f_vertexbuffer = 0;
9178         rsurface.passcolor4f_bufferoffset = 0;
9179         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9180         {
9181                 c2[0] = c[0] * r;
9182                 c2[1] = c[1] * g;
9183                 c2[2] = c[2] * b;
9184                 c2[3] = c[3] * a;
9185         }
9186 }
9187
9188 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9189 {
9190         int i;
9191         const float *c;
9192         float *c2;
9193         if (!rsurface.passcolor4f)
9194                 return;
9195         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9196         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9197         rsurface.passcolor4f_vertexbuffer = 0;
9198         rsurface.passcolor4f_bufferoffset = 0;
9199         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9200         {
9201                 c2[0] = c[0] + r_refdef.scene.ambient;
9202                 c2[1] = c[1] + r_refdef.scene.ambient;
9203                 c2[2] = c[2] + r_refdef.scene.ambient;
9204                 c2[3] = c[3];
9205         }
9206 }
9207
9208 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9209 {
9210         // TODO: optimize
9211         rsurface.passcolor4f = NULL;
9212         rsurface.passcolor4f_vertexbuffer = 0;
9213         rsurface.passcolor4f_bufferoffset = 0;
9214         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9215         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9216         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9217         GL_Color(r, g, b, a);
9218         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9219         RSurf_DrawBatch();
9220 }
9221
9222 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9223 {
9224         // TODO: optimize applyfog && applycolor case
9225         // just apply fog if necessary, and tint the fog color array if necessary
9226         rsurface.passcolor4f = NULL;
9227         rsurface.passcolor4f_vertexbuffer = 0;
9228         rsurface.passcolor4f_bufferoffset = 0;
9229         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9230         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9231         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9232         GL_Color(r, g, b, a);
9233         RSurf_DrawBatch();
9234 }
9235
9236 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9237 {
9238         // TODO: optimize
9239         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9240         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9241         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
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_ClampColor(void)
9250 {
9251         int i;
9252         const float *c1;
9253         float *c2;
9254         if (!rsurface.passcolor4f)
9255                 return;
9256         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9257         {
9258                 c2[0] = bound(0.0f, c1[0], 1.0f);
9259                 c2[1] = bound(0.0f, c1[1], 1.0f);
9260                 c2[2] = bound(0.0f, c1[2], 1.0f);
9261                 c2[3] = bound(0.0f, c1[3], 1.0f);
9262         }
9263 }
9264
9265 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9266 {
9267         int i;
9268         float f;
9269         const float *v;
9270         const float *n;
9271         float *c;
9272         //vec3_t eyedir;
9273
9274         // fake shading
9275         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9276         rsurface.passcolor4f_vertexbuffer = 0;
9277         rsurface.passcolor4f_bufferoffset = 0;
9278         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)
9279         {
9280                 f = -DotProduct(r_refdef.view.forward, n);
9281                 f = max(0, f);
9282                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9283                 f *= r_refdef.lightmapintensity;
9284                 Vector4Set(c, f, f, f, 1);
9285         }
9286 }
9287
9288 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9289 {
9290         RSurf_DrawBatch_GL11_ApplyFakeLight();
9291         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9292         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9293         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9294         GL_Color(r, g, b, a);
9295         RSurf_DrawBatch();
9296 }
9297
9298 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9299 {
9300         int i;
9301         float f;
9302         float alpha;
9303         const float *v;
9304         const float *n;
9305         float *c;
9306         vec3_t ambientcolor;
9307         vec3_t diffusecolor;
9308         vec3_t lightdir;
9309         // TODO: optimize
9310         // model lighting
9311         VectorCopy(rsurface.modellight_lightdir, lightdir);
9312         f = 0.5f * r_refdef.lightmapintensity;
9313         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9314         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9315         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9316         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9317         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9318         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9319         alpha = *a;
9320         if (VectorLength2(diffusecolor) > 0)
9321         {
9322                 // q3-style directional shading
9323                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9324                 rsurface.passcolor4f_vertexbuffer = 0;
9325                 rsurface.passcolor4f_bufferoffset = 0;
9326                 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)
9327                 {
9328                         if ((f = DotProduct(n, lightdir)) > 0)
9329                                 VectorMA(ambientcolor, f, diffusecolor, c);
9330                         else
9331                                 VectorCopy(ambientcolor, c);
9332                         c[3] = alpha;
9333                 }
9334                 *r = 1;
9335                 *g = 1;
9336                 *b = 1;
9337                 *a = 1;
9338                 *applycolor = false;
9339         }
9340         else
9341         {
9342                 *r = ambientcolor[0];
9343                 *g = ambientcolor[1];
9344                 *b = ambientcolor[2];
9345                 rsurface.passcolor4f = NULL;
9346                 rsurface.passcolor4f_vertexbuffer = 0;
9347                 rsurface.passcolor4f_bufferoffset = 0;
9348         }
9349 }
9350
9351 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9352 {
9353         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9354         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9355         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9356         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9357         GL_Color(r, g, b, a);
9358         RSurf_DrawBatch();
9359 }
9360
9361 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9362 {
9363         int i;
9364         float f;
9365         const float *v;
9366         float *c;
9367
9368         // fake shading
9369         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9370         rsurface.passcolor4f_vertexbuffer = 0;
9371         rsurface.passcolor4f_bufferoffset = 0;
9372
9373         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9374         {
9375                 f = 1 - RSurf_FogVertex(v);
9376                 c[0] = r;
9377                 c[1] = g;
9378                 c[2] = b;
9379                 c[3] = f * a;
9380         }
9381 }
9382
9383 void RSurf_SetupDepthAndCulling(void)
9384 {
9385         // submodels are biased to avoid z-fighting with world surfaces that they
9386         // may be exactly overlapping (avoids z-fighting artifacts on certain
9387         // doors and things in Quake maps)
9388         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9389         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9390         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9391         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9392 }
9393
9394 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9395 {
9396         // transparent sky would be ridiculous
9397         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9398                 return;
9399         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9400         skyrenderlater = true;
9401         RSurf_SetupDepthAndCulling();
9402         GL_DepthMask(true);
9403         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9404         // skymasking on them, and Quake3 never did sky masking (unlike
9405         // software Quake and software Quake2), so disable the sky masking
9406         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9407         // and skymasking also looks very bad when noclipping outside the
9408         // level, so don't use it then either.
9409         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9410         {
9411                 R_Mesh_ResetTextureState();
9412                 if (skyrendermasked)
9413                 {
9414                         R_SetupShader_DepthOrShadow();
9415                         // depth-only (masking)
9416                         GL_ColorMask(0,0,0,0);
9417                         // just to make sure that braindead drivers don't draw
9418                         // anything despite that colormask...
9419                         GL_BlendFunc(GL_ZERO, GL_ONE);
9420                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9421                         if (rsurface.batchvertex3fbuffer)
9422                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9423                         else
9424                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9425                 }
9426                 else
9427                 {
9428                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9429                         // fog sky
9430                         GL_BlendFunc(GL_ONE, GL_ZERO);
9431                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9432                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9433                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9434                 }
9435                 RSurf_DrawBatch();
9436                 if (skyrendermasked)
9437                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9438         }
9439         R_Mesh_ResetTextureState();
9440         GL_Color(1, 1, 1, 1);
9441 }
9442
9443 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9444 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9445 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9446 {
9447         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9448                 return;
9449         if (prepass)
9450         {
9451                 // render screenspace normalmap to texture
9452                 GL_DepthMask(true);
9453                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9454                 RSurf_DrawBatch();
9455                 return;
9456         }
9457
9458         // bind lightmap texture
9459
9460         // water/refraction/reflection/camera surfaces have to be handled specially
9461         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9462         {
9463                 int start, end, startplaneindex;
9464                 for (start = 0;start < texturenumsurfaces;start = end)
9465                 {
9466                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9467                         if(startplaneindex < 0)
9468                         {
9469                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9470                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9471                                 end = start + 1;
9472                                 continue;
9473                         }
9474                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9475                                 ;
9476                         // now that we have a batch using the same planeindex, render it
9477                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9478                         {
9479                                 // render water or distortion background
9480                                 GL_DepthMask(true);
9481                                 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));
9482                                 RSurf_DrawBatch();
9483                                 // blend surface on top
9484                                 GL_DepthMask(false);
9485                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9486                                 RSurf_DrawBatch();
9487                         }
9488                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9489                         {
9490                                 // render surface with reflection texture as input
9491                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9492                                 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));
9493                                 RSurf_DrawBatch();
9494                         }
9495                 }
9496                 return;
9497         }
9498
9499         // render surface batch normally
9500         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9501         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9502         RSurf_DrawBatch();
9503 }
9504
9505 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9506 {
9507         // OpenGL 1.3 path - anything not completely ancient
9508         qboolean applycolor;
9509         qboolean applyfog;
9510         int layerindex;
9511         const texturelayer_t *layer;
9512         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);
9513         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9514
9515         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9516         {
9517                 vec4_t layercolor;
9518                 int layertexrgbscale;
9519                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9520                 {
9521                         if (layerindex == 0)
9522                                 GL_AlphaTest(true);
9523                         else
9524                         {
9525                                 GL_AlphaTest(false);
9526                                 GL_DepthFunc(GL_EQUAL);
9527                         }
9528                 }
9529                 GL_DepthMask(layer->depthmask && writedepth);
9530                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9531                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9532                 {
9533                         layertexrgbscale = 4;
9534                         VectorScale(layer->color, 0.25f, layercolor);
9535                 }
9536                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9537                 {
9538                         layertexrgbscale = 2;
9539                         VectorScale(layer->color, 0.5f, layercolor);
9540                 }
9541                 else
9542                 {
9543                         layertexrgbscale = 1;
9544                         VectorScale(layer->color, 1.0f, layercolor);
9545                 }
9546                 layercolor[3] = layer->color[3];
9547                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9548                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9549                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9550                 switch (layer->type)
9551                 {
9552                 case TEXTURELAYERTYPE_LITTEXTURE:
9553                         // single-pass lightmapped texture with 2x rgbscale
9554                         R_Mesh_TexBind(0, r_texture_white);
9555                         R_Mesh_TexMatrix(0, NULL);
9556                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9557                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9558                         R_Mesh_TexBind(1, layer->texture);
9559                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9560                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9561                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9562                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9563                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9564                         else if (FAKELIGHT_ENABLED)
9565                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9566                         else if (rsurface.uselightmaptexture)
9567                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9568                         else
9569                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9570                         break;
9571                 case TEXTURELAYERTYPE_TEXTURE:
9572                         // singletexture unlit texture with transparency support
9573                         R_Mesh_TexBind(0, layer->texture);
9574                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9575                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9576                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9577                         R_Mesh_TexBind(1, 0);
9578                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9579                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9580                         break;
9581                 case TEXTURELAYERTYPE_FOG:
9582                         // singletexture fogging
9583                         if (layer->texture)
9584                         {
9585                                 R_Mesh_TexBind(0, layer->texture);
9586                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9587                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9588                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9589                         }
9590                         else
9591                         {
9592                                 R_Mesh_TexBind(0, 0);
9593                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9594                         }
9595                         R_Mesh_TexBind(1, 0);
9596                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9597                         // generate a color array for the fog pass
9598                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9599                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9600                         RSurf_DrawBatch();
9601                         break;
9602                 default:
9603                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9604                 }
9605         }
9606         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9607         {
9608                 GL_DepthFunc(GL_LEQUAL);
9609                 GL_AlphaTest(false);
9610         }
9611 }
9612
9613 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9614 {
9615         // OpenGL 1.1 - crusty old voodoo path
9616         qboolean applyfog;
9617         int layerindex;
9618         const texturelayer_t *layer;
9619         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);
9620         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9621
9622         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9623         {
9624                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9625                 {
9626                         if (layerindex == 0)
9627                                 GL_AlphaTest(true);
9628                         else
9629                         {
9630                                 GL_AlphaTest(false);
9631                                 GL_DepthFunc(GL_EQUAL);
9632                         }
9633                 }
9634                 GL_DepthMask(layer->depthmask && writedepth);
9635                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9636                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9637                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9638                 switch (layer->type)
9639                 {
9640                 case TEXTURELAYERTYPE_LITTEXTURE:
9641                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9642                         {
9643                                 // two-pass lit texture with 2x rgbscale
9644                                 // first the lightmap pass
9645                                 R_Mesh_TexBind(0, r_texture_white);
9646                                 R_Mesh_TexMatrix(0, NULL);
9647                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9648                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9649                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9650                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9651                                 else if (FAKELIGHT_ENABLED)
9652                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9653                                 else if (rsurface.uselightmaptexture)
9654                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9655                                 else
9656                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9657                                 // then apply the texture to it
9658                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9659                                 R_Mesh_TexBind(0, layer->texture);
9660                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9661                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9662                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9663                                 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);
9664                         }
9665                         else
9666                         {
9667                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9668                                 R_Mesh_TexBind(0, layer->texture);
9669                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9670                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9671                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9672                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9673                                         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);
9674                                 else
9675                                         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);
9676                         }
9677                         break;
9678                 case TEXTURELAYERTYPE_TEXTURE:
9679                         // singletexture unlit texture with transparency support
9680                         R_Mesh_TexBind(0, layer->texture);
9681                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9682                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9683                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9684                         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);
9685                         break;
9686                 case TEXTURELAYERTYPE_FOG:
9687                         // singletexture fogging
9688                         if (layer->texture)
9689                         {
9690                                 R_Mesh_TexBind(0, layer->texture);
9691                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9692                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9693                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9694                         }
9695                         else
9696                         {
9697                                 R_Mesh_TexBind(0, 0);
9698                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9699                         }
9700                         // generate a color array for the fog pass
9701                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9702                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9703                         RSurf_DrawBatch();
9704                         break;
9705                 default:
9706                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9707                 }
9708         }
9709         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9710         {
9711                 GL_DepthFunc(GL_LEQUAL);
9712                 GL_AlphaTest(false);
9713         }
9714 }
9715
9716 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9717 {
9718         int vi;
9719         int j;
9720         r_vertexgeneric_t *batchvertex;
9721         float c[4];
9722
9723 //      R_Mesh_ResetTextureState();
9724         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9725
9726         if(rsurface.texture && rsurface.texture->currentskinframe)
9727         {
9728                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9729                 c[3] *= rsurface.texture->currentalpha;
9730         }
9731         else
9732         {
9733                 c[0] = 1;
9734                 c[1] = 0;
9735                 c[2] = 1;
9736                 c[3] = 1;
9737         }
9738
9739         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9740         {
9741                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9742                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9743                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9744         }
9745
9746         // brighten it up (as texture value 127 means "unlit")
9747         c[0] *= 2 * r_refdef.view.colorscale;
9748         c[1] *= 2 * r_refdef.view.colorscale;
9749         c[2] *= 2 * r_refdef.view.colorscale;
9750
9751         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9752                 c[3] *= r_wateralpha.value;
9753
9754         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9755         {
9756                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9757                 GL_DepthMask(false);
9758         }
9759         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9760         {
9761                 GL_BlendFunc(GL_ONE, GL_ONE);
9762                 GL_DepthMask(false);
9763         }
9764         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9765         {
9766                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9767                 GL_DepthMask(false);
9768         }
9769         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9770         {
9771                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9772                 GL_DepthMask(false);
9773         }
9774         else
9775         {
9776                 GL_BlendFunc(GL_ONE, GL_ZERO);
9777                 GL_DepthMask(writedepth);
9778         }
9779
9780         if (r_showsurfaces.integer == 3)
9781         {
9782                 rsurface.passcolor4f = NULL;
9783
9784                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9785                 {
9786                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9787
9788                         rsurface.passcolor4f = NULL;
9789                         rsurface.passcolor4f_vertexbuffer = 0;
9790                         rsurface.passcolor4f_bufferoffset = 0;
9791                 }
9792                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9793                 {
9794                         qboolean applycolor = true;
9795                         float one = 1.0;
9796
9797                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9798
9799                         r_refdef.lightmapintensity = 1;
9800                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9801                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9802                 }
9803                 else if (FAKELIGHT_ENABLED)
9804                 {
9805                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9806
9807                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9808                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9809                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9810                 }
9811                 else
9812                 {
9813                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9814
9815                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9816                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9817                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9818                 }
9819
9820                 if(!rsurface.passcolor4f)
9821                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9822
9823                 RSurf_DrawBatch_GL11_ApplyAmbient();
9824                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9825                 if(r_refdef.fogenabled)
9826                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9827                 RSurf_DrawBatch_GL11_ClampColor();
9828
9829                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9830                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9831                 RSurf_DrawBatch();
9832         }
9833         else if (!r_refdef.view.showdebug)
9834         {
9835                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9836                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9837                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9838                 {
9839                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9840                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9841                 }
9842                 R_Mesh_PrepareVertices_Generic_Unlock();
9843                 RSurf_DrawBatch();
9844         }
9845         else if (r_showsurfaces.integer == 4)
9846         {
9847                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9848                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9849                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9850                 {
9851                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9852                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9853                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9854                 }
9855                 R_Mesh_PrepareVertices_Generic_Unlock();
9856                 RSurf_DrawBatch();
9857         }
9858         else if (r_showsurfaces.integer == 2)
9859         {
9860                 const int *e;
9861                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9862                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9863                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9864                 {
9865                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9866                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9867                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9868                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9869                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9870                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9871                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9872                 }
9873                 R_Mesh_PrepareVertices_Generic_Unlock();
9874                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9875         }
9876         else
9877         {
9878                 int texturesurfaceindex;
9879                 int k;
9880                 const msurface_t *surface;
9881                 float surfacecolor4f[4];
9882                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9883                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9884                 vi = 0;
9885                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9886                 {
9887                         surface = texturesurfacelist[texturesurfaceindex];
9888                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9889                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9890                         for (j = 0;j < surface->num_vertices;j++)
9891                         {
9892                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9893                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9894                                 vi++;
9895                         }
9896                 }
9897                 R_Mesh_PrepareVertices_Generic_Unlock();
9898                 RSurf_DrawBatch();
9899         }
9900 }
9901
9902 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9903 {
9904         CHECKGLERROR
9905         RSurf_SetupDepthAndCulling();
9906         if (r_showsurfaces.integer)
9907         {
9908                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9909                 return;
9910         }
9911         switch (vid.renderpath)
9912         {
9913         case RENDERPATH_GL20:
9914         case RENDERPATH_D3D9:
9915         case RENDERPATH_D3D10:
9916         case RENDERPATH_D3D11:
9917         case RENDERPATH_SOFT:
9918         case RENDERPATH_GLES2:
9919                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9920                 break;
9921         case RENDERPATH_GL13:
9922         case RENDERPATH_GLES1:
9923                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9924                 break;
9925         case RENDERPATH_GL11:
9926                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9927                 break;
9928         }
9929         CHECKGLERROR
9930 }
9931
9932 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9933 {
9934         CHECKGLERROR
9935         RSurf_SetupDepthAndCulling();
9936         if (r_showsurfaces.integer)
9937         {
9938                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9939                 return;
9940         }
9941         switch (vid.renderpath)
9942         {
9943         case RENDERPATH_GL20:
9944         case RENDERPATH_D3D9:
9945         case RENDERPATH_D3D10:
9946         case RENDERPATH_D3D11:
9947         case RENDERPATH_SOFT:
9948         case RENDERPATH_GLES2:
9949                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9950                 break;
9951         case RENDERPATH_GL13:
9952         case RENDERPATH_GLES1:
9953                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9954                 break;
9955         case RENDERPATH_GL11:
9956                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9957                 break;
9958         }
9959         CHECKGLERROR
9960 }
9961
9962 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9963 {
9964         int i, j;
9965         int texturenumsurfaces, endsurface;
9966         texture_t *texture;
9967         const msurface_t *surface;
9968 #define MAXBATCH_TRANSPARENTSURFACES 256
9969         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9970
9971         // if the model is static it doesn't matter what value we give for
9972         // wantnormals and wanttangents, so this logic uses only rules applicable
9973         // to a model, knowing that they are meaningless otherwise
9974         if (ent == r_refdef.scene.worldentity)
9975                 RSurf_ActiveWorldEntity();
9976         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9977                 RSurf_ActiveModelEntity(ent, false, false, false);
9978         else
9979         {
9980                 switch (vid.renderpath)
9981                 {
9982                 case RENDERPATH_GL20:
9983                 case RENDERPATH_D3D9:
9984                 case RENDERPATH_D3D10:
9985                 case RENDERPATH_D3D11:
9986                 case RENDERPATH_SOFT:
9987                 case RENDERPATH_GLES2:
9988                         RSurf_ActiveModelEntity(ent, true, true, false);
9989                         break;
9990                 case RENDERPATH_GL11:
9991                 case RENDERPATH_GL13:
9992                 case RENDERPATH_GLES1:
9993                         RSurf_ActiveModelEntity(ent, true, false, false);
9994                         break;
9995                 }
9996         }
9997
9998         if (r_transparentdepthmasking.integer)
9999         {
10000                 qboolean setup = false;
10001                 for (i = 0;i < numsurfaces;i = j)
10002                 {
10003                         j = i + 1;
10004                         surface = rsurface.modelsurfaces + surfacelist[i];
10005                         texture = surface->texture;
10006                         rsurface.texture = R_GetCurrentTexture(texture);
10007                         rsurface.lightmaptexture = NULL;
10008                         rsurface.deluxemaptexture = NULL;
10009                         rsurface.uselightmaptexture = false;
10010                         // scan ahead until we find a different texture
10011                         endsurface = min(i + 1024, numsurfaces);
10012                         texturenumsurfaces = 0;
10013                         texturesurfacelist[texturenumsurfaces++] = surface;
10014                         for (;j < endsurface;j++)
10015                         {
10016                                 surface = rsurface.modelsurfaces + surfacelist[j];
10017                                 if (texture != surface->texture)
10018                                         break;
10019                                 texturesurfacelist[texturenumsurfaces++] = surface;
10020                         }
10021                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10022                                 continue;
10023                         // render the range of surfaces as depth
10024                         if (!setup)
10025                         {
10026                                 setup = true;
10027                                 GL_ColorMask(0,0,0,0);
10028                                 GL_Color(1,1,1,1);
10029                                 GL_DepthTest(true);
10030                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10031                                 GL_DepthMask(true);
10032 //                              R_Mesh_ResetTextureState();
10033                                 R_SetupShader_DepthOrShadow();
10034                         }
10035                         RSurf_SetupDepthAndCulling();
10036                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10037                         if (rsurface.batchvertex3fbuffer)
10038                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10039                         else
10040                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10041                         RSurf_DrawBatch();
10042                 }
10043                 if (setup)
10044                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10045         }
10046
10047         for (i = 0;i < numsurfaces;i = j)
10048         {
10049                 j = i + 1;
10050                 surface = rsurface.modelsurfaces + surfacelist[i];
10051                 texture = surface->texture;
10052                 rsurface.texture = R_GetCurrentTexture(texture);
10053                 // scan ahead until we find a different texture
10054                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10055                 texturenumsurfaces = 0;
10056                 texturesurfacelist[texturenumsurfaces++] = surface;
10057                 if(FAKELIGHT_ENABLED)
10058                 {
10059                         rsurface.lightmaptexture = NULL;
10060                         rsurface.deluxemaptexture = NULL;
10061                         rsurface.uselightmaptexture = false;
10062                         for (;j < endsurface;j++)
10063                         {
10064                                 surface = rsurface.modelsurfaces + surfacelist[j];
10065                                 if (texture != surface->texture)
10066                                         break;
10067                                 texturesurfacelist[texturenumsurfaces++] = surface;
10068                         }
10069                 }
10070                 else
10071                 {
10072                         rsurface.lightmaptexture = surface->lightmaptexture;
10073                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10074                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10075                         for (;j < endsurface;j++)
10076                         {
10077                                 surface = rsurface.modelsurfaces + surfacelist[j];
10078                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10079                                         break;
10080                                 texturesurfacelist[texturenumsurfaces++] = surface;
10081                         }
10082                 }
10083                 // render the range of surfaces
10084                 if (ent == r_refdef.scene.worldentity)
10085                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10086                 else
10087                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10088         }
10089         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10090 }
10091
10092 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10093 {
10094         // transparent surfaces get pushed off into the transparent queue
10095         int surfacelistindex;
10096         const msurface_t *surface;
10097         vec3_t tempcenter, center;
10098         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10099         {
10100                 surface = texturesurfacelist[surfacelistindex];
10101                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10102                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10103                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10104                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10105                 if (queueentity->transparent_offset) // transparent offset
10106                 {
10107                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10108                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10109                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10110                 }
10111                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10112         }
10113 }
10114
10115 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10116 {
10117         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10118                 return;
10119         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10120                 return;
10121         RSurf_SetupDepthAndCulling();
10122         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10123         if (rsurface.batchvertex3fbuffer)
10124                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10125         else
10126                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10127         RSurf_DrawBatch();
10128 }
10129
10130 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10131 {
10132         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10133         CHECKGLERROR
10134         if (depthonly)
10135                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10136         else if (prepass)
10137         {
10138                 if (!rsurface.texture->currentnumlayers)
10139                         return;
10140                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10141                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10142                 else
10143                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10144         }
10145         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10146                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10147         else if (!rsurface.texture->currentnumlayers)
10148                 return;
10149         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10150         {
10151                 // in the deferred case, transparent surfaces were queued during prepass
10152                 if (!r_shadow_usingdeferredprepass)
10153                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10154         }
10155         else
10156         {
10157                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10158                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10159         }
10160         CHECKGLERROR
10161 }
10162
10163 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10164 {
10165         int i, j;
10166         texture_t *texture;
10167         R_FrameData_SetMark();
10168         // break the surface list down into batches by texture and use of lightmapping
10169         for (i = 0;i < numsurfaces;i = j)
10170         {
10171                 j = i + 1;
10172                 // texture is the base texture pointer, rsurface.texture is the
10173                 // current frame/skin the texture is directing us to use (for example
10174                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10175                 // use skin 1 instead)
10176                 texture = surfacelist[i]->texture;
10177                 rsurface.texture = R_GetCurrentTexture(texture);
10178                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10179                 {
10180                         // if this texture is not the kind we want, skip ahead to the next one
10181                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10182                                 ;
10183                         continue;
10184                 }
10185                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10186                 {
10187                         rsurface.lightmaptexture = NULL;
10188                         rsurface.deluxemaptexture = NULL;
10189                         rsurface.uselightmaptexture = false;
10190                         // simply scan ahead until we find a different texture or lightmap state
10191                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10192                                 ;
10193                 }
10194                 else
10195                 {
10196                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10197                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10198                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10199                         // simply scan ahead until we find a different texture or lightmap state
10200                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10201                                 ;
10202                 }
10203                 // render the range of surfaces
10204                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10205         }
10206         R_FrameData_ReturnToMark();
10207 }
10208
10209 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10210 {
10211         CHECKGLERROR
10212         if (depthonly)
10213                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10214         else if (prepass)
10215         {
10216                 if (!rsurface.texture->currentnumlayers)
10217                         return;
10218                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10219                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10220                 else
10221                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10222         }
10223         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10224                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10225         else if (!rsurface.texture->currentnumlayers)
10226                 return;
10227         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10228         {
10229                 // in the deferred case, transparent surfaces were queued during prepass
10230                 if (!r_shadow_usingdeferredprepass)
10231                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10232         }
10233         else
10234         {
10235                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10236                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10237         }
10238         CHECKGLERROR
10239 }
10240
10241 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10242 {
10243         int i, j;
10244         texture_t *texture;
10245         R_FrameData_SetMark();
10246         // break the surface list down into batches by texture and use of lightmapping
10247         for (i = 0;i < numsurfaces;i = j)
10248         {
10249                 j = i + 1;
10250                 // texture is the base texture pointer, rsurface.texture is the
10251                 // current frame/skin the texture is directing us to use (for example
10252                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10253                 // use skin 1 instead)
10254                 texture = surfacelist[i]->texture;
10255                 rsurface.texture = R_GetCurrentTexture(texture);
10256                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10257                 {
10258                         // if this texture is not the kind we want, skip ahead to the next one
10259                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10260                                 ;
10261                         continue;
10262                 }
10263                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10264                 {
10265                         rsurface.lightmaptexture = NULL;
10266                         rsurface.deluxemaptexture = NULL;
10267                         rsurface.uselightmaptexture = false;
10268                         // simply scan ahead until we find a different texture or lightmap state
10269                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10270                                 ;
10271                 }
10272                 else
10273                 {
10274                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10275                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10276                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10277                         // simply scan ahead until we find a different texture or lightmap state
10278                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10279                                 ;
10280                 }
10281                 // render the range of surfaces
10282                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10283         }
10284         R_FrameData_ReturnToMark();
10285 }
10286
10287 float locboxvertex3f[6*4*3] =
10288 {
10289         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10290         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10291         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10292         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10293         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10294         1,0,0, 0,0,0, 0,1,0, 1,1,0
10295 };
10296
10297 unsigned short locboxelements[6*2*3] =
10298 {
10299          0, 1, 2, 0, 2, 3,
10300          4, 5, 6, 4, 6, 7,
10301          8, 9,10, 8,10,11,
10302         12,13,14, 12,14,15,
10303         16,17,18, 16,18,19,
10304         20,21,22, 20,22,23
10305 };
10306
10307 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10308 {
10309         int i, j;
10310         cl_locnode_t *loc = (cl_locnode_t *)ent;
10311         vec3_t mins, size;
10312         float vertex3f[6*4*3];
10313         CHECKGLERROR
10314         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10315         GL_DepthMask(false);
10316         GL_DepthRange(0, 1);
10317         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10318         GL_DepthTest(true);
10319         GL_CullFace(GL_NONE);
10320         R_EntityMatrix(&identitymatrix);
10321
10322 //      R_Mesh_ResetTextureState();
10323
10324         i = surfacelist[0];
10325         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10326                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10327                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10328                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10329
10330         if (VectorCompare(loc->mins, loc->maxs))
10331         {
10332                 VectorSet(size, 2, 2, 2);
10333                 VectorMA(loc->mins, -0.5f, size, mins);
10334         }
10335         else
10336         {
10337                 VectorCopy(loc->mins, mins);
10338                 VectorSubtract(loc->maxs, loc->mins, size);
10339         }
10340
10341         for (i = 0;i < 6*4*3;)
10342                 for (j = 0;j < 3;j++, i++)
10343                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10344
10345         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10346         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10347         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10348 }
10349
10350 void R_DrawLocs(void)
10351 {
10352         int index;
10353         cl_locnode_t *loc, *nearestloc;
10354         vec3_t center;
10355         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10356         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10357         {
10358                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10359                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10360         }
10361 }
10362
10363 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10364 {
10365         if (decalsystem->decals)
10366                 Mem_Free(decalsystem->decals);
10367         memset(decalsystem, 0, sizeof(*decalsystem));
10368 }
10369
10370 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)
10371 {
10372         tridecal_t *decal;
10373         tridecal_t *decals;
10374         int i;
10375
10376         // expand or initialize the system
10377         if (decalsystem->maxdecals <= decalsystem->numdecals)
10378         {
10379                 decalsystem_t old = *decalsystem;
10380                 qboolean useshortelements;
10381                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10382                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10383                 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)));
10384                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10385                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10386                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10387                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10388                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10389                 if (decalsystem->numdecals)
10390                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10391                 if (old.decals)
10392                         Mem_Free(old.decals);
10393                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10394                         decalsystem->element3i[i] = i;
10395                 if (useshortelements)
10396                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10397                                 decalsystem->element3s[i] = i;
10398         }
10399
10400         // grab a decal and search for another free slot for the next one
10401         decals = decalsystem->decals;
10402         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10403         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10404                 ;
10405         decalsystem->freedecal = i;
10406         if (decalsystem->numdecals <= i)
10407                 decalsystem->numdecals = i + 1;
10408
10409         // initialize the decal
10410         decal->lived = 0;
10411         decal->triangleindex = triangleindex;
10412         decal->surfaceindex = surfaceindex;
10413         decal->decalsequence = decalsequence;
10414         decal->color4f[0][0] = c0[0];
10415         decal->color4f[0][1] = c0[1];
10416         decal->color4f[0][2] = c0[2];
10417         decal->color4f[0][3] = 1;
10418         decal->color4f[1][0] = c1[0];
10419         decal->color4f[1][1] = c1[1];
10420         decal->color4f[1][2] = c1[2];
10421         decal->color4f[1][3] = 1;
10422         decal->color4f[2][0] = c2[0];
10423         decal->color4f[2][1] = c2[1];
10424         decal->color4f[2][2] = c2[2];
10425         decal->color4f[2][3] = 1;
10426         decal->vertex3f[0][0] = v0[0];
10427         decal->vertex3f[0][1] = v0[1];
10428         decal->vertex3f[0][2] = v0[2];
10429         decal->vertex3f[1][0] = v1[0];
10430         decal->vertex3f[1][1] = v1[1];
10431         decal->vertex3f[1][2] = v1[2];
10432         decal->vertex3f[2][0] = v2[0];
10433         decal->vertex3f[2][1] = v2[1];
10434         decal->vertex3f[2][2] = v2[2];
10435         decal->texcoord2f[0][0] = t0[0];
10436         decal->texcoord2f[0][1] = t0[1];
10437         decal->texcoord2f[1][0] = t1[0];
10438         decal->texcoord2f[1][1] = t1[1];
10439         decal->texcoord2f[2][0] = t2[0];
10440         decal->texcoord2f[2][1] = t2[1];
10441         TriangleNormal(v0, v1, v2, decal->plane);
10442         VectorNormalize(decal->plane);
10443         decal->plane[3] = DotProduct(v0, decal->plane);
10444 }
10445
10446 extern cvar_t cl_decals_bias;
10447 extern cvar_t cl_decals_models;
10448 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10449 // baseparms, parms, temps
10450 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)
10451 {
10452         int cornerindex;
10453         int index;
10454         float v[9][3];
10455         const float *vertex3f;
10456         const float *normal3f;
10457         int numpoints;
10458         float points[2][9][3];
10459         float temp[3];
10460         float tc[9][2];
10461         float f;
10462         float c[9][4];
10463         const int *e;
10464
10465         e = rsurface.modelelement3i + 3*triangleindex;
10466
10467         vertex3f = rsurface.modelvertex3f;
10468         normal3f = rsurface.modelnormal3f;
10469
10470         if (normal3f)
10471         {
10472                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10473                 {
10474                         index = 3*e[cornerindex];
10475                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10476                 }
10477         }
10478         else
10479         {
10480                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10481                 {
10482                         index = 3*e[cornerindex];
10483                         VectorCopy(vertex3f + index, v[cornerindex]);
10484                 }
10485         }
10486
10487         // cull backfaces
10488         //TriangleNormal(v[0], v[1], v[2], normal);
10489         //if (DotProduct(normal, localnormal) < 0.0f)
10490         //      continue;
10491         // clip by each of the box planes formed from the projection matrix
10492         // if anything survives, we emit the decal
10493         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]);
10494         if (numpoints < 3)
10495                 return;
10496         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]);
10497         if (numpoints < 3)
10498                 return;
10499         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]);
10500         if (numpoints < 3)
10501                 return;
10502         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]);
10503         if (numpoints < 3)
10504                 return;
10505         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]);
10506         if (numpoints < 3)
10507                 return;
10508         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]);
10509         if (numpoints < 3)
10510                 return;
10511         // some part of the triangle survived, so we have to accept it...
10512         if (dynamic)
10513         {
10514                 // dynamic always uses the original triangle
10515                 numpoints = 3;
10516                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10517                 {
10518                         index = 3*e[cornerindex];
10519                         VectorCopy(vertex3f + index, v[cornerindex]);
10520                 }
10521         }
10522         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10523         {
10524                 // convert vertex positions to texcoords
10525                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10526                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10527                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10528                 // calculate distance fade from the projection origin
10529                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10530                 f = bound(0.0f, f, 1.0f);
10531                 c[cornerindex][0] = r * f;
10532                 c[cornerindex][1] = g * f;
10533                 c[cornerindex][2] = b * f;
10534                 c[cornerindex][3] = 1.0f;
10535                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10536         }
10537         if (dynamic)
10538                 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);
10539         else
10540                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10541                         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);
10542 }
10543 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)
10544 {
10545         matrix4x4_t projection;
10546         decalsystem_t *decalsystem;
10547         qboolean dynamic;
10548         dp_model_t *model;
10549         const msurface_t *surface;
10550         const msurface_t *surfaces;
10551         const int *surfacelist;
10552         const texture_t *texture;
10553         int numtriangles;
10554         int numsurfacelist;
10555         int surfacelistindex;
10556         int surfaceindex;
10557         int triangleindex;
10558         float localorigin[3];
10559         float localnormal[3];
10560         float localmins[3];
10561         float localmaxs[3];
10562         float localsize;
10563         //float normal[3];
10564         float planes[6][4];
10565         float angles[3];
10566         bih_t *bih;
10567         int bih_triangles_count;
10568         int bih_triangles[256];
10569         int bih_surfaces[256];
10570
10571         decalsystem = &ent->decalsystem;
10572         model = ent->model;
10573         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10574         {
10575                 R_DecalSystem_Reset(&ent->decalsystem);
10576                 return;
10577         }
10578
10579         if (!model->brush.data_leafs && !cl_decals_models.integer)
10580         {
10581                 if (decalsystem->model)
10582                         R_DecalSystem_Reset(decalsystem);
10583                 return;
10584         }
10585
10586         if (decalsystem->model != model)
10587                 R_DecalSystem_Reset(decalsystem);
10588         decalsystem->model = model;
10589
10590         RSurf_ActiveModelEntity(ent, true, false, false);
10591
10592         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10593         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10594         VectorNormalize(localnormal);
10595         localsize = worldsize*rsurface.inversematrixscale;
10596         localmins[0] = localorigin[0] - localsize;
10597         localmins[1] = localorigin[1] - localsize;
10598         localmins[2] = localorigin[2] - localsize;
10599         localmaxs[0] = localorigin[0] + localsize;
10600         localmaxs[1] = localorigin[1] + localsize;
10601         localmaxs[2] = localorigin[2] + localsize;
10602
10603         //VectorCopy(localnormal, planes[4]);
10604         //VectorVectors(planes[4], planes[2], planes[0]);
10605         AnglesFromVectors(angles, localnormal, NULL, false);
10606         AngleVectors(angles, planes[0], planes[2], planes[4]);
10607         VectorNegate(planes[0], planes[1]);
10608         VectorNegate(planes[2], planes[3]);
10609         VectorNegate(planes[4], planes[5]);
10610         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10611         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10612         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10613         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10614         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10615         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10616
10617 #if 1
10618 // works
10619 {
10620         matrix4x4_t forwardprojection;
10621         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10622         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10623 }
10624 #else
10625 // broken
10626 {
10627         float projectionvector[4][3];
10628         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10629         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10630         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10631         projectionvector[0][0] = planes[0][0] * ilocalsize;
10632         projectionvector[0][1] = planes[1][0] * ilocalsize;
10633         projectionvector[0][2] = planes[2][0] * ilocalsize;
10634         projectionvector[1][0] = planes[0][1] * ilocalsize;
10635         projectionvector[1][1] = planes[1][1] * ilocalsize;
10636         projectionvector[1][2] = planes[2][1] * ilocalsize;
10637         projectionvector[2][0] = planes[0][2] * ilocalsize;
10638         projectionvector[2][1] = planes[1][2] * ilocalsize;
10639         projectionvector[2][2] = planes[2][2] * ilocalsize;
10640         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10641         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10642         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10643         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10644 }
10645 #endif
10646
10647         dynamic = model->surfmesh.isanimated;
10648         numsurfacelist = model->nummodelsurfaces;
10649         surfacelist = model->sortedmodelsurfaces;
10650         surfaces = model->data_surfaces;
10651
10652         bih = NULL;
10653         bih_triangles_count = -1;
10654         if(!dynamic)
10655         {
10656                 if(model->render_bih.numleafs)
10657                         bih = &model->render_bih;
10658                 else if(model->collision_bih.numleafs)
10659                         bih = &model->collision_bih;
10660         }
10661         if(bih)
10662                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10663         if(bih_triangles_count == 0)
10664                 return;
10665         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10666                 return;
10667         if(bih_triangles_count > 0)
10668         {
10669                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10670                 {
10671                         surfaceindex = bih_surfaces[triangleindex];
10672                         surface = surfaces + surfaceindex;
10673                         texture = surface->texture;
10674                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10675                                 continue;
10676                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10677                                 continue;
10678                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10679                 }
10680         }
10681         else
10682         {
10683                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10684                 {
10685                         surfaceindex = surfacelist[surfacelistindex];
10686                         surface = surfaces + surfaceindex;
10687                         // check cull box first because it rejects more than any other check
10688                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10689                                 continue;
10690                         // skip transparent surfaces
10691                         texture = surface->texture;
10692                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10693                                 continue;
10694                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10695                                 continue;
10696                         numtriangles = surface->num_triangles;
10697                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10698                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10699                 }
10700         }
10701 }
10702
10703 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10704 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)
10705 {
10706         int renderentityindex;
10707         float worldmins[3];
10708         float worldmaxs[3];
10709         entity_render_t *ent;
10710
10711         if (!cl_decals_newsystem.integer)
10712                 return;
10713
10714         worldmins[0] = worldorigin[0] - worldsize;
10715         worldmins[1] = worldorigin[1] - worldsize;
10716         worldmins[2] = worldorigin[2] - worldsize;
10717         worldmaxs[0] = worldorigin[0] + worldsize;
10718         worldmaxs[1] = worldorigin[1] + worldsize;
10719         worldmaxs[2] = worldorigin[2] + worldsize;
10720
10721         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10722
10723         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10724         {
10725                 ent = r_refdef.scene.entities[renderentityindex];
10726                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10727                         continue;
10728
10729                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10730         }
10731 }
10732
10733 typedef struct r_decalsystem_splatqueue_s
10734 {
10735         vec3_t worldorigin;
10736         vec3_t worldnormal;
10737         float color[4];
10738         float tcrange[4];
10739         float worldsize;
10740         int decalsequence;
10741 }
10742 r_decalsystem_splatqueue_t;
10743
10744 int r_decalsystem_numqueued = 0;
10745 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10746
10747 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)
10748 {
10749         r_decalsystem_splatqueue_t *queue;
10750
10751         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10752                 return;
10753
10754         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10755         VectorCopy(worldorigin, queue->worldorigin);
10756         VectorCopy(worldnormal, queue->worldnormal);
10757         Vector4Set(queue->color, r, g, b, a);
10758         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10759         queue->worldsize = worldsize;
10760         queue->decalsequence = cl.decalsequence++;
10761 }
10762
10763 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10764 {
10765         int i;
10766         r_decalsystem_splatqueue_t *queue;
10767
10768         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10769                 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);
10770         r_decalsystem_numqueued = 0;
10771 }
10772
10773 extern cvar_t cl_decals_max;
10774 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10775 {
10776         int i;
10777         decalsystem_t *decalsystem = &ent->decalsystem;
10778         int numdecals;
10779         int killsequence;
10780         tridecal_t *decal;
10781         float frametime;
10782         float lifetime;
10783
10784         if (!decalsystem->numdecals)
10785                 return;
10786
10787         if (r_showsurfaces.integer)
10788                 return;
10789
10790         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10791         {
10792                 R_DecalSystem_Reset(decalsystem);
10793                 return;
10794         }
10795
10796         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10797         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10798
10799         if (decalsystem->lastupdatetime)
10800                 frametime = (cl.time - decalsystem->lastupdatetime);
10801         else
10802                 frametime = 0;
10803         decalsystem->lastupdatetime = cl.time;
10804         decal = decalsystem->decals;
10805         numdecals = decalsystem->numdecals;
10806
10807         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10808         {
10809                 if (decal->color4f[0][3])
10810                 {
10811                         decal->lived += frametime;
10812                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10813                         {
10814                                 memset(decal, 0, sizeof(*decal));
10815                                 if (decalsystem->freedecal > i)
10816                                         decalsystem->freedecal = i;
10817                         }
10818                 }
10819         }
10820         decal = decalsystem->decals;
10821         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10822                 numdecals--;
10823
10824         // collapse the array by shuffling the tail decals into the gaps
10825         for (;;)
10826         {
10827                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10828                         decalsystem->freedecal++;
10829                 if (decalsystem->freedecal == numdecals)
10830                         break;
10831                 decal[decalsystem->freedecal] = decal[--numdecals];
10832         }
10833
10834         decalsystem->numdecals = numdecals;
10835
10836         if (numdecals <= 0)
10837         {
10838                 // if there are no decals left, reset decalsystem
10839                 R_DecalSystem_Reset(decalsystem);
10840         }
10841 }
10842
10843 extern skinframe_t *decalskinframe;
10844 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10845 {
10846         int i;
10847         decalsystem_t *decalsystem = &ent->decalsystem;
10848         int numdecals;
10849         tridecal_t *decal;
10850         float faderate;
10851         float alpha;
10852         float *v3f;
10853         float *c4f;
10854         float *t2f;
10855         const int *e;
10856         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10857         int numtris = 0;
10858
10859         numdecals = decalsystem->numdecals;
10860         if (!numdecals)
10861                 return;
10862
10863         if (r_showsurfaces.integer)
10864                 return;
10865
10866         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10867         {
10868                 R_DecalSystem_Reset(decalsystem);
10869                 return;
10870         }
10871
10872         // if the model is static it doesn't matter what value we give for
10873         // wantnormals and wanttangents, so this logic uses only rules applicable
10874         // to a model, knowing that they are meaningless otherwise
10875         if (ent == r_refdef.scene.worldentity)
10876                 RSurf_ActiveWorldEntity();
10877         else
10878                 RSurf_ActiveModelEntity(ent, false, false, false);
10879
10880         decalsystem->lastupdatetime = cl.time;
10881         decal = decalsystem->decals;
10882
10883         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10884
10885         // update vertex positions for animated models
10886         v3f = decalsystem->vertex3f;
10887         c4f = decalsystem->color4f;
10888         t2f = decalsystem->texcoord2f;
10889         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10890         {
10891                 if (!decal->color4f[0][3])
10892                         continue;
10893
10894                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10895                         continue;
10896
10897                 // skip backfaces
10898                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10899                         continue;
10900
10901                 // update color values for fading decals
10902                 if (decal->lived >= cl_decals_time.value)
10903                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10904                 else
10905                         alpha = 1.0f;
10906
10907                 c4f[ 0] = decal->color4f[0][0] * alpha;
10908                 c4f[ 1] = decal->color4f[0][1] * alpha;
10909                 c4f[ 2] = decal->color4f[0][2] * alpha;
10910                 c4f[ 3] = 1;
10911                 c4f[ 4] = decal->color4f[1][0] * alpha;
10912                 c4f[ 5] = decal->color4f[1][1] * alpha;
10913                 c4f[ 6] = decal->color4f[1][2] * alpha;
10914                 c4f[ 7] = 1;
10915                 c4f[ 8] = decal->color4f[2][0] * alpha;
10916                 c4f[ 9] = decal->color4f[2][1] * alpha;
10917                 c4f[10] = decal->color4f[2][2] * alpha;
10918                 c4f[11] = 1;
10919
10920                 t2f[0] = decal->texcoord2f[0][0];
10921                 t2f[1] = decal->texcoord2f[0][1];
10922                 t2f[2] = decal->texcoord2f[1][0];
10923                 t2f[3] = decal->texcoord2f[1][1];
10924                 t2f[4] = decal->texcoord2f[2][0];
10925                 t2f[5] = decal->texcoord2f[2][1];
10926
10927                 // update vertex positions for animated models
10928                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10929                 {
10930                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10931                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10932                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10933                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10934                 }
10935                 else
10936                 {
10937                         VectorCopy(decal->vertex3f[0], v3f);
10938                         VectorCopy(decal->vertex3f[1], v3f + 3);
10939                         VectorCopy(decal->vertex3f[2], v3f + 6);
10940                 }
10941
10942                 if (r_refdef.fogenabled)
10943                 {
10944                         alpha = RSurf_FogVertex(v3f);
10945                         VectorScale(c4f, alpha, c4f);
10946                         alpha = RSurf_FogVertex(v3f + 3);
10947                         VectorScale(c4f + 4, alpha, c4f + 4);
10948                         alpha = RSurf_FogVertex(v3f + 6);
10949                         VectorScale(c4f + 8, alpha, c4f + 8);
10950                 }
10951
10952                 v3f += 9;
10953                 c4f += 12;
10954                 t2f += 6;
10955                 numtris++;
10956         }
10957
10958         if (numtris > 0)
10959         {
10960                 r_refdef.stats.drawndecals += numtris;
10961
10962                 // now render the decals all at once
10963                 // (this assumes they all use one particle font texture!)
10964                 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);
10965 //              R_Mesh_ResetTextureState();
10966                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10967                 GL_DepthMask(false);
10968                 GL_DepthRange(0, 1);
10969                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10970                 GL_DepthTest(true);
10971                 GL_CullFace(GL_NONE);
10972                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10973                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10974                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10975         }
10976 }
10977
10978 static void R_DrawModelDecals(void)
10979 {
10980         int i, numdecals;
10981
10982         // fade faster when there are too many decals
10983         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10984         for (i = 0;i < r_refdef.scene.numentities;i++)
10985                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10986
10987         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10988         for (i = 0;i < r_refdef.scene.numentities;i++)
10989                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10990                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10991
10992         R_DecalSystem_ApplySplatEntitiesQueue();
10993
10994         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10995         for (i = 0;i < r_refdef.scene.numentities;i++)
10996                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10997
10998         r_refdef.stats.totaldecals += numdecals;
10999
11000         if (r_showsurfaces.integer)
11001                 return;
11002
11003         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11004
11005         for (i = 0;i < r_refdef.scene.numentities;i++)
11006         {
11007                 if (!r_refdef.viewcache.entityvisible[i])
11008                         continue;
11009                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11010                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11011         }
11012 }
11013
11014 extern cvar_t mod_collision_bih;
11015 void R_DrawDebugModel(void)
11016 {
11017         entity_render_t *ent = rsurface.entity;
11018         int i, j, k, l, flagsmask;
11019         const msurface_t *surface;
11020         dp_model_t *model = ent->model;
11021         vec3_t v;
11022
11023         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11024                 return;
11025
11026         if (r_showoverdraw.value > 0)
11027         {
11028                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11029                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11030                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11031                 GL_DepthTest(false);
11032                 GL_DepthMask(false);
11033                 GL_DepthRange(0, 1);
11034                 GL_BlendFunc(GL_ONE, GL_ONE);
11035                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11036                 {
11037                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11038                                 continue;
11039                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11040                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11041                         {
11042                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11043                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11044                                 if (!rsurface.texture->currentlayers->depthmask)
11045                                         GL_Color(c, 0, 0, 1.0f);
11046                                 else if (ent == r_refdef.scene.worldentity)
11047                                         GL_Color(c, c, c, 1.0f);
11048                                 else
11049                                         GL_Color(0, c, 0, 1.0f);
11050                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11051                                 RSurf_DrawBatch();
11052                         }
11053                 }
11054                 rsurface.texture = NULL;
11055         }
11056
11057         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11058
11059 //      R_Mesh_ResetTextureState();
11060         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11061         GL_DepthRange(0, 1);
11062         GL_DepthTest(!r_showdisabledepthtest.integer);
11063         GL_DepthMask(false);
11064         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11065
11066         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11067         {
11068                 int triangleindex;
11069                 int bihleafindex;
11070                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11071                 const q3mbrush_t *brush;
11072                 const bih_t *bih = &model->collision_bih;
11073                 const bih_leaf_t *bihleaf;
11074                 float vertex3f[3][3];
11075                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11076                 cullbox = false;
11077                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11078                 {
11079                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11080                                 continue;
11081                         switch (bihleaf->type)
11082                         {
11083                         case BIH_BRUSH:
11084                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11085                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11086                                 {
11087                                         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);
11088                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11089                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11090                                 }
11091                                 break;
11092                         case BIH_COLLISIONTRIANGLE:
11093                                 triangleindex = bihleaf->itemindex;
11094                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11095                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11096                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11097                                 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);
11098                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11099                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11100                                 break;
11101                         case BIH_RENDERTRIANGLE:
11102                                 triangleindex = bihleaf->itemindex;
11103                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11104                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11105                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11106                                 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);
11107                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11108                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11109                                 break;
11110                         }
11111                 }
11112         }
11113
11114         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11115
11116         if (r_showtris.integer && qglPolygonMode)
11117         {
11118                 if (r_showdisabledepthtest.integer)
11119                 {
11120                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11121                         GL_DepthMask(false);
11122                 }
11123                 else
11124                 {
11125                         GL_BlendFunc(GL_ONE, GL_ZERO);
11126                         GL_DepthMask(true);
11127                 }
11128                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11129                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11130                 {
11131                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11132                                 continue;
11133                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11134                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11135                         {
11136                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11137                                 if (!rsurface.texture->currentlayers->depthmask)
11138                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11139                                 else if (ent == r_refdef.scene.worldentity)
11140                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11141                                 else
11142                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11143                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11144                                 RSurf_DrawBatch();
11145                         }
11146                 }
11147                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11148                 rsurface.texture = NULL;
11149         }
11150
11151         if (r_shownormals.value != 0 && qglBegin)
11152         {
11153                 if (r_showdisabledepthtest.integer)
11154                 {
11155                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11156                         GL_DepthMask(false);
11157                 }
11158                 else
11159                 {
11160                         GL_BlendFunc(GL_ONE, GL_ZERO);
11161                         GL_DepthMask(true);
11162                 }
11163                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11164                 {
11165                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11166                                 continue;
11167                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11168                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11169                         {
11170                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11171                                 qglBegin(GL_LINES);
11172                                 if (r_shownormals.value < 0)
11173                                 {
11174                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11175                                         {
11176                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11177                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11178                                                 qglVertex3f(v[0], v[1], v[2]);
11179                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11180                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11181                                                 qglVertex3f(v[0], v[1], v[2]);
11182                                         }
11183                                 }
11184                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11185                                 {
11186                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11187                                         {
11188                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11189                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11190                                                 qglVertex3f(v[0], v[1], v[2]);
11191                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11192                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11193                                                 qglVertex3f(v[0], v[1], v[2]);
11194                                         }
11195                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11196                                         {
11197                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11198                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11199                                                 qglVertex3f(v[0], v[1], v[2]);
11200                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11201                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11202                                                 qglVertex3f(v[0], v[1], v[2]);
11203                                         }
11204                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11205                                         {
11206                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11207                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11208                                                 qglVertex3f(v[0], v[1], v[2]);
11209                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11210                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11211                                                 qglVertex3f(v[0], v[1], v[2]);
11212                                         }
11213                                 }
11214                                 qglEnd();
11215                                 CHECKGLERROR
11216                         }
11217                 }
11218                 rsurface.texture = NULL;
11219         }
11220 }
11221
11222 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11223 int r_maxsurfacelist = 0;
11224 const msurface_t **r_surfacelist = NULL;
11225 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11226 {
11227         int i, j, endj, flagsmask;
11228         dp_model_t *model = r_refdef.scene.worldmodel;
11229         msurface_t *surfaces;
11230         unsigned char *update;
11231         int numsurfacelist = 0;
11232         if (model == NULL)
11233                 return;
11234
11235         if (r_maxsurfacelist < model->num_surfaces)
11236         {
11237                 r_maxsurfacelist = model->num_surfaces;
11238                 if (r_surfacelist)
11239                         Mem_Free((msurface_t**)r_surfacelist);
11240                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11241         }
11242
11243         RSurf_ActiveWorldEntity();
11244
11245         surfaces = model->data_surfaces;
11246         update = model->brushq1.lightmapupdateflags;
11247
11248         // update light styles on this submodel
11249         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11250         {
11251                 model_brush_lightstyleinfo_t *style;
11252                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11253                 {
11254                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11255                         {
11256                                 int *list = style->surfacelist;
11257                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11258                                 for (j = 0;j < style->numsurfaces;j++)
11259                                         update[list[j]] = true;
11260                         }
11261                 }
11262         }
11263
11264         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11265
11266         if (debug)
11267         {
11268                 R_DrawDebugModel();
11269                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11270                 return;
11271         }
11272
11273         rsurface.lightmaptexture = NULL;
11274         rsurface.deluxemaptexture = NULL;
11275         rsurface.uselightmaptexture = false;
11276         rsurface.texture = NULL;
11277         rsurface.rtlight = NULL;
11278         numsurfacelist = 0;
11279         // add visible surfaces to draw list
11280         for (i = 0;i < model->nummodelsurfaces;i++)
11281         {
11282                 j = model->sortedmodelsurfaces[i];
11283                 if (r_refdef.viewcache.world_surfacevisible[j])
11284                         r_surfacelist[numsurfacelist++] = surfaces + j;
11285         }
11286         // update lightmaps if needed
11287         if (model->brushq1.firstrender)
11288         {
11289                 model->brushq1.firstrender = false;
11290                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11291                         if (update[j])
11292                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11293         }
11294         else if (update)
11295         {
11296                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11297                         if (r_refdef.viewcache.world_surfacevisible[j])
11298                                 if (update[j])
11299                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11300         }
11301         // don't do anything if there were no surfaces
11302         if (!numsurfacelist)
11303         {
11304                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11305                 return;
11306         }
11307         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11308
11309         // add to stats if desired
11310         if (r_speeds.integer && !skysurfaces && !depthonly)
11311         {
11312                 r_refdef.stats.world_surfaces += numsurfacelist;
11313                 for (j = 0;j < numsurfacelist;j++)
11314                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11315         }
11316
11317         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11318 }
11319
11320 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11321 {
11322         int i, j, endj, flagsmask;
11323         dp_model_t *model = ent->model;
11324         msurface_t *surfaces;
11325         unsigned char *update;
11326         int numsurfacelist = 0;
11327         if (model == NULL)
11328                 return;
11329
11330         if (r_maxsurfacelist < model->num_surfaces)
11331         {
11332                 r_maxsurfacelist = model->num_surfaces;
11333                 if (r_surfacelist)
11334                         Mem_Free((msurface_t **)r_surfacelist);
11335                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11336         }
11337
11338         // if the model is static it doesn't matter what value we give for
11339         // wantnormals and wanttangents, so this logic uses only rules applicable
11340         // to a model, knowing that they are meaningless otherwise
11341         if (ent == r_refdef.scene.worldentity)
11342                 RSurf_ActiveWorldEntity();
11343         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11344                 RSurf_ActiveModelEntity(ent, false, false, false);
11345         else if (prepass)
11346                 RSurf_ActiveModelEntity(ent, true, true, true);
11347         else if (depthonly)
11348         {
11349                 switch (vid.renderpath)
11350                 {
11351                 case RENDERPATH_GL20:
11352                 case RENDERPATH_D3D9:
11353                 case RENDERPATH_D3D10:
11354                 case RENDERPATH_D3D11:
11355                 case RENDERPATH_SOFT:
11356                 case RENDERPATH_GLES2:
11357                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11358                         break;
11359                 case RENDERPATH_GL11:
11360                 case RENDERPATH_GL13:
11361                 case RENDERPATH_GLES1:
11362                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11363                         break;
11364                 }
11365         }
11366         else
11367         {
11368                 switch (vid.renderpath)
11369                 {
11370                 case RENDERPATH_GL20:
11371                 case RENDERPATH_D3D9:
11372                 case RENDERPATH_D3D10:
11373                 case RENDERPATH_D3D11:
11374                 case RENDERPATH_SOFT:
11375                 case RENDERPATH_GLES2:
11376                         RSurf_ActiveModelEntity(ent, true, true, false);
11377                         break;
11378                 case RENDERPATH_GL11:
11379                 case RENDERPATH_GL13:
11380                 case RENDERPATH_GLES1:
11381                         RSurf_ActiveModelEntity(ent, true, false, false);
11382                         break;
11383                 }
11384         }
11385
11386         surfaces = model->data_surfaces;
11387         update = model->brushq1.lightmapupdateflags;
11388
11389         // update light styles
11390         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11391         {
11392                 model_brush_lightstyleinfo_t *style;
11393                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11394                 {
11395                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11396                         {
11397                                 int *list = style->surfacelist;
11398                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11399                                 for (j = 0;j < style->numsurfaces;j++)
11400                                         update[list[j]] = true;
11401                         }
11402                 }
11403         }
11404
11405         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11406
11407         if (debug)
11408         {
11409                 R_DrawDebugModel();
11410                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11411                 return;
11412         }
11413
11414         rsurface.lightmaptexture = NULL;
11415         rsurface.deluxemaptexture = NULL;
11416         rsurface.uselightmaptexture = false;
11417         rsurface.texture = NULL;
11418         rsurface.rtlight = NULL;
11419         numsurfacelist = 0;
11420         // add visible surfaces to draw list
11421         for (i = 0;i < model->nummodelsurfaces;i++)
11422                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11423         // don't do anything if there were no surfaces
11424         if (!numsurfacelist)
11425         {
11426                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11427                 return;
11428         }
11429         // update lightmaps if needed
11430         if (update)
11431         {
11432                 int updated = 0;
11433                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11434                 {
11435                         if (update[j])
11436                         {
11437                                 updated++;
11438                                 R_BuildLightMap(ent, surfaces + j);
11439                         }
11440                 }
11441         }
11442         if (update)
11443                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11444                         if (update[j])
11445                                 R_BuildLightMap(ent, surfaces + j);
11446         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11447
11448         // add to stats if desired
11449         if (r_speeds.integer && !skysurfaces && !depthonly)
11450         {
11451                 r_refdef.stats.entities_surfaces += numsurfacelist;
11452                 for (j = 0;j < numsurfacelist;j++)
11453                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11454         }
11455
11456         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11457 }
11458
11459 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11460 {
11461         static texture_t texture;
11462         static msurface_t surface;
11463         const msurface_t *surfacelist = &surface;
11464
11465         // fake enough texture and surface state to render this geometry
11466
11467         texture.update_lastrenderframe = -1; // regenerate this texture
11468         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11469         texture.currentskinframe = skinframe;
11470         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11471         texture.offsetmapping = OFFSETMAPPING_OFF;
11472         texture.offsetscale = 1;
11473         texture.specularscalemod = 1;
11474         texture.specularpowermod = 1;
11475
11476         surface.texture = &texture;
11477         surface.num_triangles = numtriangles;
11478         surface.num_firsttriangle = firsttriangle;
11479         surface.num_vertices = numvertices;
11480         surface.num_firstvertex = firstvertex;
11481
11482         // now render it
11483         rsurface.texture = R_GetCurrentTexture(surface.texture);
11484         rsurface.lightmaptexture = NULL;
11485         rsurface.deluxemaptexture = NULL;
11486         rsurface.uselightmaptexture = false;
11487         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11488 }
11489
11490 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)
11491 {
11492         static msurface_t surface;
11493         const msurface_t *surfacelist = &surface;
11494
11495         // fake enough texture and surface state to render this geometry
11496         surface.texture = texture;
11497         surface.num_triangles = numtriangles;
11498         surface.num_firsttriangle = firsttriangle;
11499         surface.num_vertices = numvertices;
11500         surface.num_firstvertex = firstvertex;
11501
11502         // now render it
11503         rsurface.texture = R_GetCurrentTexture(surface.texture);
11504         rsurface.lightmaptexture = NULL;
11505         rsurface.deluxemaptexture = NULL;
11506         rsurface.uselightmaptexture = false;
11507         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11508 }