]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix a segfault in menu routing when switching gamedirs
[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_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
74 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
75 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)"};
76 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
77 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
78 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"};
79 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"};
80 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
81 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"};
82 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"};
83 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"};
84 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
85 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
86 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
87 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
88 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
89 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
90 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
91 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)"};
92 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)"};
93 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
94 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
95 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
96 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97
98 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
99 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
100 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101
102 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
103 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
104 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
105 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."};
106 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
107 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
108 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
109 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."};
110 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
111 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
112 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
113 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
114 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"};
115 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"};
116 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
118 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
119 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
120 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
121 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"};
122
123 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
124 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
125 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
126 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
127 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
128 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
129 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
130 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
131
132 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)"};
133 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"};
134
135 cvar_t r_texture_sRGB_2d = {0, "r_texture_sRGB_2d", "0", "load textures as sRGB"};
136 cvar_t r_texture_sRGB_skin_diffuse = {0, "r_texture_sRGB_skin_diffuse", "0", "load textures as sRGB"};
137 cvar_t r_texture_sRGB_skin_gloss = {0, "r_texture_sRGB_skin_gloss", "0", "load textures as sRGB"};
138 cvar_t r_texture_sRGB_skin_glow = {0, "r_texture_sRGB_skin_glow", "0", "load textures as sRGB"};
139 cvar_t r_texture_sRGB_skin_reflect = {0, "r_texture_sRGB_skin_reflect", "0", "load textures as sRGB"};
140 cvar_t r_texture_sRGB_cubemap = {0, "r_texture_sRGB_cubemap", "0", "load textures as sRGB"};
141 cvar_t r_texture_sRGB_skybox = {0, "r_texture_sRGB_skybox", "0", "load textures as sRGB"};
142
143 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
144 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
145 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
146
147 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"};
148 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"};
149 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
150 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
151 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"};
152 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)"};
153 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)"};
154 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
155
156 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)"};
157 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
158 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)"};
159 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
160 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)"};
161 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)"};
162 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
163 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
164 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)"};
165 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)"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172
173 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)"};
174 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
175 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"};
176 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
177 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
178 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
179
180 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
181 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
182 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
183 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
184
185 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
186 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
187 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
188 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
189 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
190 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
191 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
192
193 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
194 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
195 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
196 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)"};
197 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
198 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
199 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
200 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
201 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
202 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
203
204 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"};
205
206 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"};
207
208 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
209
210 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
211 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"};
212 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
213 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
214 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
215 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
216 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)"};
217 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
218 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
219
220 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
221 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"};
222
223 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."};
224
225 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)"};
226
227 extern cvar_t v_glslgamma;
228
229 extern qboolean v_flipped_state;
230
231 static struct r_bloomstate_s
232 {
233         qboolean enabled;
234         qboolean hdr;
235
236         int bloomwidth, bloomheight;
237
238         textype_t texturetype;
239         int viewfbo; // used to check if r_viewfbo cvar has changed
240
241         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
242         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
243         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
244
245         int screentexturewidth, screentextureheight;
246         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
247
248         int bloomtexturewidth, bloomtextureheight;
249         rtexture_t *texture_bloom;
250
251         // arrays for rendering the screen passes
252         float screentexcoord2f[8];
253         float bloomtexcoord2f[8];
254         float offsettexcoord2f[8];
255
256         r_viewport_t viewport;
257 }
258 r_bloomstate;
259
260 r_waterstate_t r_waterstate;
261
262 /// shadow volume bsp struct with automatically growing nodes buffer
263 svbsp_t r_svbsp;
264
265 rtexture_t *r_texture_blanknormalmap;
266 rtexture_t *r_texture_white;
267 rtexture_t *r_texture_grey128;
268 rtexture_t *r_texture_black;
269 rtexture_t *r_texture_notexture;
270 rtexture_t *r_texture_whitecube;
271 rtexture_t *r_texture_normalizationcube;
272 rtexture_t *r_texture_fogattenuation;
273 rtexture_t *r_texture_fogheighttexture;
274 rtexture_t *r_texture_gammaramps;
275 unsigned int r_texture_gammaramps_serial;
276 //rtexture_t *r_texture_fogintensity;
277 rtexture_t *r_texture_reflectcube;
278
279 // TODO: hash lookups?
280 typedef struct cubemapinfo_s
281 {
282         char basename[64];
283         rtexture_t *texture;
284 }
285 cubemapinfo_t;
286
287 int r_texture_numcubemaps;
288 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
289
290 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
291 unsigned int r_numqueries;
292 unsigned int r_maxqueries;
293
294 typedef struct r_qwskincache_s
295 {
296         char name[MAX_QPATH];
297         skinframe_t *skinframe;
298 }
299 r_qwskincache_t;
300
301 static r_qwskincache_t *r_qwskincache;
302 static int r_qwskincache_size;
303
304 /// vertex coordinates for a quad that covers the screen exactly
305 extern const float r_screenvertex3f[12];
306 extern const float r_d3dscreenvertex3f[12];
307 const float r_screenvertex3f[12] =
308 {
309         0, 0, 0,
310         1, 0, 0,
311         1, 1, 0,
312         0, 1, 0
313 };
314 const float r_d3dscreenvertex3f[12] =
315 {
316         0, 1, 0,
317         1, 1, 0,
318         1, 0, 0,
319         0, 0, 0
320 };
321
322 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
323 {
324         int i;
325         for (i = 0;i < verts;i++)
326         {
327                 out[0] = in[0] * r;
328                 out[1] = in[1] * g;
329                 out[2] = in[2] * b;
330                 out[3] = in[3];
331                 in += 4;
332                 out += 4;
333         }
334 }
335
336 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
337 {
338         int i;
339         for (i = 0;i < verts;i++)
340         {
341                 out[0] = r;
342                 out[1] = g;
343                 out[2] = b;
344                 out[3] = a;
345                 out += 4;
346         }
347 }
348
349 // FIXME: move this to client?
350 void FOG_clear(void)
351 {
352         if (gamemode == GAME_NEHAHRA)
353         {
354                 Cvar_Set("gl_fogenable", "0");
355                 Cvar_Set("gl_fogdensity", "0.2");
356                 Cvar_Set("gl_fogred", "0.3");
357                 Cvar_Set("gl_foggreen", "0.3");
358                 Cvar_Set("gl_fogblue", "0.3");
359         }
360         r_refdef.fog_density = 0;
361         r_refdef.fog_red = 0;
362         r_refdef.fog_green = 0;
363         r_refdef.fog_blue = 0;
364         r_refdef.fog_alpha = 1;
365         r_refdef.fog_start = 0;
366         r_refdef.fog_end = 16384;
367         r_refdef.fog_height = 1<<30;
368         r_refdef.fog_fadedepth = 128;
369         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
370 }
371
372 static void R_BuildBlankTextures(void)
373 {
374         unsigned char data[4];
375         data[2] = 128; // normal X
376         data[1] = 128; // normal Y
377         data[0] = 255; // normal Z
378         data[3] = 128; // height
379         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 255;
381         data[1] = 255;
382         data[2] = 255;
383         data[3] = 255;
384         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385         data[0] = 128;
386         data[1] = 128;
387         data[2] = 128;
388         data[3] = 255;
389         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390         data[0] = 0;
391         data[1] = 0;
392         data[2] = 0;
393         data[3] = 255;
394         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
395 }
396
397 static void R_BuildNoTexture(void)
398 {
399         int x, y;
400         unsigned char pix[16][16][4];
401         // this makes a light grey/dark grey checkerboard texture
402         for (y = 0;y < 16;y++)
403         {
404                 for (x = 0;x < 16;x++)
405                 {
406                         if ((y < 8) ^ (x < 8))
407                         {
408                                 pix[y][x][0] = 128;
409                                 pix[y][x][1] = 128;
410                                 pix[y][x][2] = 128;
411                                 pix[y][x][3] = 255;
412                         }
413                         else
414                         {
415                                 pix[y][x][0] = 64;
416                                 pix[y][x][1] = 64;
417                                 pix[y][x][2] = 64;
418                                 pix[y][x][3] = 255;
419                         }
420                 }
421         }
422         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
423 }
424
425 static void R_BuildWhiteCube(void)
426 {
427         unsigned char data[6*1*1*4];
428         memset(data, 255, sizeof(data));
429         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
430 }
431
432 static void R_BuildNormalizationCube(void)
433 {
434         int x, y, side;
435         vec3_t v;
436         vec_t s, t, intensity;
437 #define NORMSIZE 64
438         unsigned char *data;
439         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
440         for (side = 0;side < 6;side++)
441         {
442                 for (y = 0;y < NORMSIZE;y++)
443                 {
444                         for (x = 0;x < NORMSIZE;x++)
445                         {
446                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
447                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
448                                 switch(side)
449                                 {
450                                 default:
451                                 case 0:
452                                         v[0] = 1;
453                                         v[1] = -t;
454                                         v[2] = -s;
455                                         break;
456                                 case 1:
457                                         v[0] = -1;
458                                         v[1] = -t;
459                                         v[2] = s;
460                                         break;
461                                 case 2:
462                                         v[0] = s;
463                                         v[1] = 1;
464                                         v[2] = t;
465                                         break;
466                                 case 3:
467                                         v[0] = s;
468                                         v[1] = -1;
469                                         v[2] = -t;
470                                         break;
471                                 case 4:
472                                         v[0] = s;
473                                         v[1] = -t;
474                                         v[2] = 1;
475                                         break;
476                                 case 5:
477                                         v[0] = -s;
478                                         v[1] = -t;
479                                         v[2] = -1;
480                                         break;
481                                 }
482                                 intensity = 127.0f / sqrt(DotProduct(v, v));
483                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
484                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
485                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
486                                 data[((side*64+y)*64+x)*4+3] = 255;
487                         }
488                 }
489         }
490         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
491         Mem_Free(data);
492 }
493
494 static void R_BuildFogTexture(void)
495 {
496         int x, b;
497 #define FOGWIDTH 256
498         unsigned char data1[FOGWIDTH][4];
499         //unsigned char data2[FOGWIDTH][4];
500         double d, r, alpha;
501
502         r_refdef.fogmasktable_start = r_refdef.fog_start;
503         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
504         r_refdef.fogmasktable_range = r_refdef.fogrange;
505         r_refdef.fogmasktable_density = r_refdef.fog_density;
506
507         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
508         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
509         {
510                 d = (x * r - r_refdef.fogmasktable_start);
511                 if(developer_extra.integer)
512                         Con_DPrintf("%f ", d);
513                 d = max(0, d);
514                 if (r_fog_exp2.integer)
515                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
516                 else
517                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
518                 if(developer_extra.integer)
519                         Con_DPrintf(" : %f ", alpha);
520                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
521                 if(developer_extra.integer)
522                         Con_DPrintf(" = %f\n", alpha);
523                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
524         }
525
526         for (x = 0;x < FOGWIDTH;x++)
527         {
528                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
529                 data1[x][0] = b;
530                 data1[x][1] = b;
531                 data1[x][2] = b;
532                 data1[x][3] = 255;
533                 //data2[x][0] = 255 - b;
534                 //data2[x][1] = 255 - b;
535                 //data2[x][2] = 255 - b;
536                 //data2[x][3] = 255;
537         }
538         if (r_texture_fogattenuation)
539         {
540                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
542         }
543         else
544         {
545                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
546                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
547         }
548 }
549
550 static void R_BuildFogHeightTexture(void)
551 {
552         unsigned char *inpixels;
553         int size;
554         int x;
555         int y;
556         int j;
557         float c[4];
558         float f;
559         inpixels = NULL;
560         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
561         if (r_refdef.fogheighttexturename[0])
562                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
563         if (!inpixels)
564         {
565                 r_refdef.fog_height_tablesize = 0;
566                 if (r_texture_fogheighttexture)
567                         R_FreeTexture(r_texture_fogheighttexture);
568                 r_texture_fogheighttexture = NULL;
569                 if (r_refdef.fog_height_table2d)
570                         Mem_Free(r_refdef.fog_height_table2d);
571                 r_refdef.fog_height_table2d = NULL;
572                 if (r_refdef.fog_height_table1d)
573                         Mem_Free(r_refdef.fog_height_table1d);
574                 r_refdef.fog_height_table1d = NULL;
575                 return;
576         }
577         size = image_width;
578         r_refdef.fog_height_tablesize = size;
579         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
580         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
581         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
582         Mem_Free(inpixels);
583         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
584         // average fog color table accounting for every fog layer between a point
585         // and the camera.  (Note: attenuation is handled separately!)
586         for (y = 0;y < size;y++)
587         {
588                 for (x = 0;x < size;x++)
589                 {
590                         Vector4Clear(c);
591                         f = 0;
592                         if (x < y)
593                         {
594                                 for (j = x;j <= y;j++)
595                                 {
596                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
597                                         f++;
598                                 }
599                         }
600                         else
601                         {
602                                 for (j = x;j >= y;j--)
603                                 {
604                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605                                         f++;
606                                 }
607                         }
608                         f = 1.0f / f;
609                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
610                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
611                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
612                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
613                 }
614         }
615         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
616 }
617
618 //=======================================================================================================================================================
619
620 static const char *builtinshaderstring =
621 #include "shader_glsl.h"
622 ;
623
624 const char *builtinhlslshaderstring =
625 #include "shader_hlsl.h"
626 ;
627
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
630
631 //=======================================================================================================================================================
632
633 typedef struct shaderpermutationinfo_s
634 {
635         const char *pretext;
636         const char *name;
637 }
638 shaderpermutationinfo_t;
639
640 typedef struct shadermodeinfo_s
641 {
642         const char *vertexfilename;
643         const char *geometryfilename;
644         const char *fragmentfilename;
645         const char *pretext;
646         const char *name;
647 }
648 shadermodeinfo_t;
649
650 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
651 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
652 {
653         {"#define USEDIFFUSE\n", " diffuse"},
654         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
655         {"#define USEVIEWTINT\n", " viewtint"},
656         {"#define USECOLORMAPPING\n", " colormapping"},
657         {"#define USESATURATION\n", " saturation"},
658         {"#define USEFOGINSIDE\n", " foginside"},
659         {"#define USEFOGOUTSIDE\n", " fogoutside"},
660         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
661         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
662         {"#define USEGAMMARAMPS\n", " gammaramps"},
663         {"#define USECUBEFILTER\n", " cubefilter"},
664         {"#define USEGLOW\n", " glow"},
665         {"#define USEBLOOM\n", " bloom"},
666         {"#define USESPECULAR\n", " specular"},
667         {"#define USEPOSTPROCESSING\n", " postprocessing"},
668         {"#define USEREFLECTION\n", " reflection"},
669         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
670         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
671         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
672         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
673         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
674         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
675         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
676         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
677         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
678         {"#define USEALPHAKILL\n", " alphakill"},
679         {"#define USEREFLECTCUBE\n", " reflectcube"},
680         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
681         {"#define USEBOUNCEGRID\n", " bouncegrid"},
682         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
683 };
684
685 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
686 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
687 {
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 };
705
706 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
707 {
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
724 };
725
726 struct r_glsl_permutation_s;
727 typedef struct r_glsl_permutation_s
728 {
729         /// hash lookup data
730         struct r_glsl_permutation_s *hashnext;
731         unsigned int mode;
732         unsigned int permutation;
733
734         /// indicates if we have tried compiling this permutation already
735         qboolean compiled;
736         /// 0 if compilation failed
737         int program;
738         // texture units assigned to each detected uniform
739         int tex_Texture_First;
740         int tex_Texture_Second;
741         int tex_Texture_GammaRamps;
742         int tex_Texture_Normal;
743         int tex_Texture_Color;
744         int tex_Texture_Gloss;
745         int tex_Texture_Glow;
746         int tex_Texture_SecondaryNormal;
747         int tex_Texture_SecondaryColor;
748         int tex_Texture_SecondaryGloss;
749         int tex_Texture_SecondaryGlow;
750         int tex_Texture_Pants;
751         int tex_Texture_Shirt;
752         int tex_Texture_FogHeightTexture;
753         int tex_Texture_FogMask;
754         int tex_Texture_Lightmap;
755         int tex_Texture_Deluxemap;
756         int tex_Texture_Attenuation;
757         int tex_Texture_Cube;
758         int tex_Texture_Refraction;
759         int tex_Texture_Reflection;
760         int tex_Texture_ShadowMap2D;
761         int tex_Texture_CubeProjection;
762         int tex_Texture_ScreenDepth;
763         int tex_Texture_ScreenNormalMap;
764         int tex_Texture_ScreenDiffuse;
765         int tex_Texture_ScreenSpecular;
766         int tex_Texture_ReflectMask;
767         int tex_Texture_ReflectCube;
768         int tex_Texture_BounceGrid;
769         /// locations of detected uniforms in program object, or -1 if not found
770         int loc_Texture_First;
771         int loc_Texture_Second;
772         int loc_Texture_GammaRamps;
773         int loc_Texture_Normal;
774         int loc_Texture_Color;
775         int loc_Texture_Gloss;
776         int loc_Texture_Glow;
777         int loc_Texture_SecondaryNormal;
778         int loc_Texture_SecondaryColor;
779         int loc_Texture_SecondaryGloss;
780         int loc_Texture_SecondaryGlow;
781         int loc_Texture_Pants;
782         int loc_Texture_Shirt;
783         int loc_Texture_FogHeightTexture;
784         int loc_Texture_FogMask;
785         int loc_Texture_Lightmap;
786         int loc_Texture_Deluxemap;
787         int loc_Texture_Attenuation;
788         int loc_Texture_Cube;
789         int loc_Texture_Refraction;
790         int loc_Texture_Reflection;
791         int loc_Texture_ShadowMap2D;
792         int loc_Texture_CubeProjection;
793         int loc_Texture_ScreenDepth;
794         int loc_Texture_ScreenNormalMap;
795         int loc_Texture_ScreenDiffuse;
796         int loc_Texture_ScreenSpecular;
797         int loc_Texture_ReflectMask;
798         int loc_Texture_ReflectCube;
799         int loc_Texture_BounceGrid;
800         int loc_Alpha;
801         int loc_BloomBlur_Parameters;
802         int loc_ClientTime;
803         int loc_Color_Ambient;
804         int loc_Color_Diffuse;
805         int loc_Color_Specular;
806         int loc_Color_Glow;
807         int loc_Color_Pants;
808         int loc_Color_Shirt;
809         int loc_DeferredColor_Ambient;
810         int loc_DeferredColor_Diffuse;
811         int loc_DeferredColor_Specular;
812         int loc_DeferredMod_Diffuse;
813         int loc_DeferredMod_Specular;
814         int loc_DistortScaleRefractReflect;
815         int loc_EyePosition;
816         int loc_FogColor;
817         int loc_FogHeightFade;
818         int loc_FogPlane;
819         int loc_FogPlaneViewDist;
820         int loc_FogRangeRecip;
821         int loc_LightColor;
822         int loc_LightDir;
823         int loc_LightPosition;
824         int loc_OffsetMapping_ScaleSteps;
825         int loc_PixelSize;
826         int loc_ReflectColor;
827         int loc_ReflectFactor;
828         int loc_ReflectOffset;
829         int loc_RefractColor;
830         int loc_Saturation;
831         int loc_ScreenCenterRefractReflect;
832         int loc_ScreenScaleRefractReflect;
833         int loc_ScreenToDepth;
834         int loc_ShadowMap_Parameters;
835         int loc_ShadowMap_TextureScale;
836         int loc_SpecularPower;
837         int loc_UserVec1;
838         int loc_UserVec2;
839         int loc_UserVec3;
840         int loc_UserVec4;
841         int loc_ViewTintColor;
842         int loc_ViewToLight;
843         int loc_ModelToLight;
844         int loc_TexMatrix;
845         int loc_BackgroundTexMatrix;
846         int loc_ModelViewProjectionMatrix;
847         int loc_ModelViewMatrix;
848         int loc_PixelToScreenTexCoord;
849         int loc_ModelToReflectCube;
850         int loc_ShadowMapMatrix;
851         int loc_BloomColorSubtract;
852         int loc_NormalmapScrollBlend;
853         int loc_BounceGridMatrix;
854         int loc_BounceGridIntensity;
855 }
856 r_glsl_permutation_t;
857
858 #define SHADERPERMUTATION_HASHSIZE 256
859
860
861 // non-degradable "lightweight" shader parameters to keep the permutations simpler
862 // these can NOT degrade! only use for simple stuff
863 enum
864 {
865         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
866         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
867         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
868         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
869         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
870         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
871         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
872 };
873 #define SHADERSTATICPARMS_COUNT 7
874
875 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
876 static int shaderstaticparms_count = 0;
877
878 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
879 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
880 qboolean R_CompileShader_CheckStaticParms(void)
881 {
882         static int r_compileshader_staticparms_save[1];
883         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
884         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
885
886         // detect all
887         if (r_glsl_saturation_redcompensate.integer)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
889         if (r_glsl_vertextextureblend_usebothalphas.integer)
890                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
891         if (r_shadow_glossexact.integer)
892                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
893         if (r_glsl_postprocess.integer)
894         {
895                 if (r_glsl_postprocess_uservec1_enable.integer)
896                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
897                 if (r_glsl_postprocess_uservec2_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
899                 if (r_glsl_postprocess_uservec3_enable.integer)
900                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
901                 if (r_glsl_postprocess_uservec4_enable.integer)
902                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
903         }
904         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
905 }
906
907 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
908         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
909                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
910         else \
911                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
912 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
913 {
914         shaderstaticparms_count = 0;
915
916         // emit all
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
924 }
925
926 /// information about each possible shader permutation
927 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
928 /// currently selected permutation
929 r_glsl_permutation_t *r_glsl_permutation;
930 /// storage for permutations linked in the hash table
931 memexpandablearray_t r_glsl_permutationarray;
932
933 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
934 {
935         //unsigned int hashdepth = 0;
936         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
937         r_glsl_permutation_t *p;
938         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
939         {
940                 if (p->mode == mode && p->permutation == permutation)
941                 {
942                         //if (hashdepth > 10)
943                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
944                         return p;
945                 }
946                 //hashdepth++;
947         }
948         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
949         p->mode = mode;
950         p->permutation = permutation;
951         p->hashnext = r_glsl_permutationhash[mode][hashindex];
952         r_glsl_permutationhash[mode][hashindex] = p;
953         //if (hashdepth > 10)
954         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
955         return p;
956 }
957
958 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
959 {
960         char *shaderstring;
961         if (!filename || !filename[0])
962                 return NULL;
963         if (!strcmp(filename, "glsl/default.glsl"))
964         {
965                 if (!glslshaderstring)
966                 {
967                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
968                         if (glslshaderstring)
969                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
970                         else
971                                 glslshaderstring = (char *)builtinshaderstring;
972                 }
973                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
974                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
975                 return shaderstring;
976         }
977         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
978         if (shaderstring)
979         {
980                 if (printfromdisknotice)
981                         Con_DPrintf("from disk %s... ", filename);
982                 return shaderstring;
983         }
984         return shaderstring;
985 }
986
987 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
988 {
989         int i;
990         int sampler;
991         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
992         char *vertexstring, *geometrystring, *fragmentstring;
993         char permutationname[256];
994         int vertstrings_count = 0;
995         int geomstrings_count = 0;
996         int fragstrings_count = 0;
997         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
998         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
999         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1000
1001         if (p->compiled)
1002                 return;
1003         p->compiled = true;
1004         p->program = 0;
1005
1006         permutationname[0] = 0;
1007         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1008         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1009         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1010
1011         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1012
1013         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1014         if(vid.support.gl20shaders130)
1015         {
1016                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1017                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1018                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1019                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1020                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1021                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1022         }
1023
1024         // the first pretext is which type of shader to compile as
1025         // (later these will all be bound together as a program object)
1026         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1027         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1028         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1029
1030         // the second pretext is the mode (for example a light source)
1031         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1032         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1033         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1034         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1035
1036         // now add all the permutation pretexts
1037         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1038         {
1039                 if (permutation & (1<<i))
1040                 {
1041                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1042                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1043                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1044                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1045                 }
1046                 else
1047                 {
1048                         // keep line numbers correct
1049                         vertstrings_list[vertstrings_count++] = "\n";
1050                         geomstrings_list[geomstrings_count++] = "\n";
1051                         fragstrings_list[fragstrings_count++] = "\n";
1052                 }
1053         }
1054
1055         // add static parms
1056         R_CompileShader_AddStaticParms(mode, permutation);
1057         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058         vertstrings_count += shaderstaticparms_count;
1059         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1060         geomstrings_count += shaderstaticparms_count;
1061         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1062         fragstrings_count += shaderstaticparms_count;
1063
1064         // now append the shader text itself
1065         vertstrings_list[vertstrings_count++] = vertexstring;
1066         geomstrings_list[geomstrings_count++] = geometrystring;
1067         fragstrings_list[fragstrings_count++] = fragmentstring;
1068
1069         // if any sources were NULL, clear the respective list
1070         if (!vertexstring)
1071                 vertstrings_count = 0;
1072         if (!geometrystring)
1073                 geomstrings_count = 0;
1074         if (!fragmentstring)
1075                 fragstrings_count = 0;
1076
1077         // compile the shader program
1078         if (vertstrings_count + geomstrings_count + fragstrings_count)
1079                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1080         if (p->program)
1081         {
1082                 CHECKGLERROR
1083                 qglUseProgram(p->program);CHECKGLERROR
1084                 // look up all the uniform variable names we care about, so we don't
1085                 // have to look them up every time we set them
1086
1087                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1088                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1089                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1090                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1091                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1092                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1093                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1094                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1095                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1096                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1097                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1098                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1099                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1100                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1101                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1102                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1103                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1104                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1105                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1106                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1107                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1108                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1109                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1110                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1111                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1112                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1113                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1114                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1115                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1116                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1117                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1118                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1119                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1120                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1121                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1122                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1123                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1124                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1125                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1126                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1127                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1128                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1129                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1130                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1131                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1132                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1133                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1134                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1135                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1136                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1137                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1138                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1139                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1140                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1141                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1142                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1143                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1144                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1145                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1146                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1147                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1148                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1149                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1150                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1151                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1152                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1153                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1154                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1155                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1156                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1157                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1158                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1159                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1160                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1161                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1162                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1163                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1164                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1165                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1166                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1167                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1168                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1169                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1170                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1171                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1172                 // initialize the samplers to refer to the texture units we use
1173                 p->tex_Texture_First = -1;
1174                 p->tex_Texture_Second = -1;
1175                 p->tex_Texture_GammaRamps = -1;
1176                 p->tex_Texture_Normal = -1;
1177                 p->tex_Texture_Color = -1;
1178                 p->tex_Texture_Gloss = -1;
1179                 p->tex_Texture_Glow = -1;
1180                 p->tex_Texture_SecondaryNormal = -1;
1181                 p->tex_Texture_SecondaryColor = -1;
1182                 p->tex_Texture_SecondaryGloss = -1;
1183                 p->tex_Texture_SecondaryGlow = -1;
1184                 p->tex_Texture_Pants = -1;
1185                 p->tex_Texture_Shirt = -1;
1186                 p->tex_Texture_FogHeightTexture = -1;
1187                 p->tex_Texture_FogMask = -1;
1188                 p->tex_Texture_Lightmap = -1;
1189                 p->tex_Texture_Deluxemap = -1;
1190                 p->tex_Texture_Attenuation = -1;
1191                 p->tex_Texture_Cube = -1;
1192                 p->tex_Texture_Refraction = -1;
1193                 p->tex_Texture_Reflection = -1;
1194                 p->tex_Texture_ShadowMap2D = -1;
1195                 p->tex_Texture_CubeProjection = -1;
1196                 p->tex_Texture_ScreenDepth = -1;
1197                 p->tex_Texture_ScreenNormalMap = -1;
1198                 p->tex_Texture_ScreenDiffuse = -1;
1199                 p->tex_Texture_ScreenSpecular = -1;
1200                 p->tex_Texture_ReflectMask = -1;
1201                 p->tex_Texture_ReflectCube = -1;
1202                 p->tex_Texture_BounceGrid = -1;
1203                 sampler = 0;
1204                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1205                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1206                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1207                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1208                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1209                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1210                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1211                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1212                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1213                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1214                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1215                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1216                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1217                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1218                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1219                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1220                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1221                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1222                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1223                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1224                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1225                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1226                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1227                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1228                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1229                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1230                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1231                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1232                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1233                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1234                 CHECKGLERROR
1235                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1236         }
1237         else
1238                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1239
1240         // free the strings
1241         if (vertexstring)
1242                 Mem_Free(vertexstring);
1243         if (geometrystring)
1244                 Mem_Free(geometrystring);
1245         if (fragmentstring)
1246                 Mem_Free(fragmentstring);
1247 }
1248
1249 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1250 {
1251         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1252         if (r_glsl_permutation != perm)
1253         {
1254                 r_glsl_permutation = perm;
1255                 if (!r_glsl_permutation->program)
1256                 {
1257                         if (!r_glsl_permutation->compiled)
1258                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1259                         if (!r_glsl_permutation->program)
1260                         {
1261                                 // remove features until we find a valid permutation
1262                                 int i;
1263                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1264                                 {
1265                                         // reduce i more quickly whenever it would not remove any bits
1266                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1267                                         if (!(permutation & j))
1268                                                 continue;
1269                                         permutation -= j;
1270                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1271                                         if (!r_glsl_permutation->compiled)
1272                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1273                                         if (r_glsl_permutation->program)
1274                                                 break;
1275                                 }
1276                                 if (i >= SHADERPERMUTATION_COUNT)
1277                                 {
1278                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1279                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1280                                         qglUseProgram(0);CHECKGLERROR
1281                                         return; // no bit left to clear, entire mode is broken
1282                                 }
1283                         }
1284                 }
1285                 CHECKGLERROR
1286                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1287         }
1288         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1289         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1290         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1291 }
1292
1293 #ifdef SUPPORTD3D
1294
1295 #ifdef SUPPORTD3D
1296 #include <d3d9.h>
1297 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1298 extern D3DCAPS9 vid_d3d9caps;
1299 #endif
1300
1301 struct r_hlsl_permutation_s;
1302 typedef struct r_hlsl_permutation_s
1303 {
1304         /// hash lookup data
1305         struct r_hlsl_permutation_s *hashnext;
1306         unsigned int mode;
1307         unsigned int permutation;
1308
1309         /// indicates if we have tried compiling this permutation already
1310         qboolean compiled;
1311         /// NULL if compilation failed
1312         IDirect3DVertexShader9 *vertexshader;
1313         IDirect3DPixelShader9 *pixelshader;
1314 }
1315 r_hlsl_permutation_t;
1316
1317 typedef enum D3DVSREGISTER_e
1318 {
1319         D3DVSREGISTER_TexMatrix = 0, // float4x4
1320         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1321         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1322         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1323         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1324         D3DVSREGISTER_ModelToLight = 20, // float4x4
1325         D3DVSREGISTER_EyePosition = 24,
1326         D3DVSREGISTER_FogPlane = 25,
1327         D3DVSREGISTER_LightDir = 26,
1328         D3DVSREGISTER_LightPosition = 27,
1329 }
1330 D3DVSREGISTER_t;
1331
1332 typedef enum D3DPSREGISTER_e
1333 {
1334         D3DPSREGISTER_Alpha = 0,
1335         D3DPSREGISTER_BloomBlur_Parameters = 1,
1336         D3DPSREGISTER_ClientTime = 2,
1337         D3DPSREGISTER_Color_Ambient = 3,
1338         D3DPSREGISTER_Color_Diffuse = 4,
1339         D3DPSREGISTER_Color_Specular = 5,
1340         D3DPSREGISTER_Color_Glow = 6,
1341         D3DPSREGISTER_Color_Pants = 7,
1342         D3DPSREGISTER_Color_Shirt = 8,
1343         D3DPSREGISTER_DeferredColor_Ambient = 9,
1344         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1345         D3DPSREGISTER_DeferredColor_Specular = 11,
1346         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1347         D3DPSREGISTER_DeferredMod_Specular = 13,
1348         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1349         D3DPSREGISTER_EyePosition = 15, // unused
1350         D3DPSREGISTER_FogColor = 16,
1351         D3DPSREGISTER_FogHeightFade = 17,
1352         D3DPSREGISTER_FogPlane = 18,
1353         D3DPSREGISTER_FogPlaneViewDist = 19,
1354         D3DPSREGISTER_FogRangeRecip = 20,
1355         D3DPSREGISTER_LightColor = 21,
1356         D3DPSREGISTER_LightDir = 22, // unused
1357         D3DPSREGISTER_LightPosition = 23,
1358         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1359         D3DPSREGISTER_PixelSize = 25,
1360         D3DPSREGISTER_ReflectColor = 26,
1361         D3DPSREGISTER_ReflectFactor = 27,
1362         D3DPSREGISTER_ReflectOffset = 28,
1363         D3DPSREGISTER_RefractColor = 29,
1364         D3DPSREGISTER_Saturation = 30,
1365         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1366         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1367         D3DPSREGISTER_ScreenToDepth = 33,
1368         D3DPSREGISTER_ShadowMap_Parameters = 34,
1369         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1370         D3DPSREGISTER_SpecularPower = 36,
1371         D3DPSREGISTER_UserVec1 = 37,
1372         D3DPSREGISTER_UserVec2 = 38,
1373         D3DPSREGISTER_UserVec3 = 39,
1374         D3DPSREGISTER_UserVec4 = 40,
1375         D3DPSREGISTER_ViewTintColor = 41,
1376         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1377         D3DPSREGISTER_BloomColorSubtract = 43,
1378         D3DPSREGISTER_ViewToLight = 44, // float4x4
1379         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1380         D3DPSREGISTER_NormalmapScrollBlend = 52,
1381         // next at 53
1382 }
1383 D3DPSREGISTER_t;
1384
1385 /// information about each possible shader permutation
1386 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1387 /// currently selected permutation
1388 r_hlsl_permutation_t *r_hlsl_permutation;
1389 /// storage for permutations linked in the hash table
1390 memexpandablearray_t r_hlsl_permutationarray;
1391
1392 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1393 {
1394         //unsigned int hashdepth = 0;
1395         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1396         r_hlsl_permutation_t *p;
1397         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1398         {
1399                 if (p->mode == mode && p->permutation == permutation)
1400                 {
1401                         //if (hashdepth > 10)
1402                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1403                         return p;
1404                 }
1405                 //hashdepth++;
1406         }
1407         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1408         p->mode = mode;
1409         p->permutation = permutation;
1410         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1411         r_hlsl_permutationhash[mode][hashindex] = p;
1412         //if (hashdepth > 10)
1413         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1414         return p;
1415 }
1416
1417 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1418 {
1419         char *shaderstring;
1420         if (!filename || !filename[0])
1421                 return NULL;
1422         if (!strcmp(filename, "hlsl/default.hlsl"))
1423         {
1424                 if (!hlslshaderstring)
1425                 {
1426                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1427                         if (hlslshaderstring)
1428                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1429                         else
1430                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1431                 }
1432                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1433                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1434                 return shaderstring;
1435         }
1436         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1437         if (shaderstring)
1438         {
1439                 if (printfromdisknotice)
1440                         Con_DPrintf("from disk %s... ", filename);
1441                 return shaderstring;
1442         }
1443         return shaderstring;
1444 }
1445
1446 #include <d3dx9.h>
1447 //#include <d3dx9shader.h>
1448 //#include <d3dx9mesh.h>
1449
1450 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1451 {
1452         DWORD *vsbin = NULL;
1453         DWORD *psbin = NULL;
1454         fs_offset_t vsbinsize;
1455         fs_offset_t psbinsize;
1456 //      IDirect3DVertexShader9 *vs = NULL;
1457 //      IDirect3DPixelShader9 *ps = NULL;
1458         ID3DXBuffer *vslog = NULL;
1459         ID3DXBuffer *vsbuffer = NULL;
1460         ID3DXConstantTable *vsconstanttable = NULL;
1461         ID3DXBuffer *pslog = NULL;
1462         ID3DXBuffer *psbuffer = NULL;
1463         ID3DXConstantTable *psconstanttable = NULL;
1464         int vsresult = 0;
1465         int psresult = 0;
1466         char temp[MAX_INPUTLINE];
1467         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1468         qboolean debugshader = gl_paranoid.integer != 0;
1469         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1470         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1471         if (!debugshader)
1472         {
1473                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1474                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1475         }
1476         if ((!vsbin && vertstring) || (!psbin && fragstring))
1477         {
1478                 const char* dllnames_d3dx9 [] =
1479                 {
1480                         "d3dx9_43.dll",
1481                         "d3dx9_42.dll",
1482                         "d3dx9_41.dll",
1483                         "d3dx9_40.dll",
1484                         "d3dx9_39.dll",
1485                         "d3dx9_38.dll",
1486                         "d3dx9_37.dll",
1487                         "d3dx9_36.dll",
1488                         "d3dx9_35.dll",
1489                         "d3dx9_34.dll",
1490                         "d3dx9_33.dll",
1491                         "d3dx9_32.dll",
1492                         "d3dx9_31.dll",
1493                         "d3dx9_30.dll",
1494                         "d3dx9_29.dll",
1495                         "d3dx9_28.dll",
1496                         "d3dx9_27.dll",
1497                         "d3dx9_26.dll",
1498                         "d3dx9_25.dll",
1499                         "d3dx9_24.dll",
1500                         NULL
1501                 };
1502                 dllhandle_t d3dx9_dll = NULL;
1503                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1504                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1505                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1506                 dllfunction_t d3dx9_dllfuncs[] =
1507                 {
1508                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1509                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1510                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1511                         {NULL, NULL}
1512                 };
1513                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1514                 {
1515                         DWORD shaderflags = 0;
1516                         if (debugshader)
1517                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1518                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1519                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1520                         if (vertstring && vertstring[0])
1521                         {
1522                                 if (debugshader)
1523                                 {
1524 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1525 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1526                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1527                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1528                                 }
1529                                 else
1530                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1531                                 if (vsbuffer)
1532                                 {
1533                                         vsbinsize = vsbuffer->GetBufferSize();
1534                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1535                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1536                                         vsbuffer->Release();
1537                                 }
1538                                 if (vslog)
1539                                 {
1540                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1541                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1542                                         vslog->Release();
1543                                 }
1544                         }
1545                         if (fragstring && fragstring[0])
1546                         {
1547                                 if (debugshader)
1548                                 {
1549 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1550 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1551                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1552                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1553                                 }
1554                                 else
1555                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1556                                 if (psbuffer)
1557                                 {
1558                                         psbinsize = psbuffer->GetBufferSize();
1559                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1560                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1561                                         psbuffer->Release();
1562                                 }
1563                                 if (pslog)
1564                                 {
1565                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1566                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1567                                         pslog->Release();
1568                                 }
1569                         }
1570                         Sys_UnloadLibrary(&d3dx9_dll);
1571                 }
1572                 else
1573                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1574         }
1575         if (vsbin && psbin)
1576         {
1577                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1578                 if (FAILED(vsresult))
1579                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1580                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1581                 if (FAILED(psresult))
1582                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1583         }
1584         // free the shader data
1585         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1586         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1587 }
1588
1589 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1590 {
1591         int i;
1592         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1593         int vertstring_length = 0;
1594         int geomstring_length = 0;
1595         int fragstring_length = 0;
1596         char *t;
1597         char *vertexstring, *geometrystring, *fragmentstring;
1598         char *vertstring, *geomstring, *fragstring;
1599         char permutationname[256];
1600         char cachename[256];
1601         int vertstrings_count = 0;
1602         int geomstrings_count = 0;
1603         int fragstrings_count = 0;
1604         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1605         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1606         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1607
1608         if (p->compiled)
1609                 return;
1610         p->compiled = true;
1611         p->vertexshader = NULL;
1612         p->pixelshader = NULL;
1613
1614         permutationname[0] = 0;
1615         cachename[0] = 0;
1616         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1617         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1618         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1619
1620         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1621         strlcat(cachename, "hlsl/", sizeof(cachename));
1622
1623         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1624         vertstrings_count = 0;
1625         geomstrings_count = 0;
1626         fragstrings_count = 0;
1627         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1628         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1629         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1630
1631         // the first pretext is which type of shader to compile as
1632         // (later these will all be bound together as a program object)
1633         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1634         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1635         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1636
1637         // the second pretext is the mode (for example a light source)
1638         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1639         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1640         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1641         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1642         strlcat(cachename, modeinfo->name, sizeof(cachename));
1643
1644         // now add all the permutation pretexts
1645         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1646         {
1647                 if (permutation & (1<<i))
1648                 {
1649                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1650                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1651                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1652                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1653                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1654                 }
1655                 else
1656                 {
1657                         // keep line numbers correct
1658                         vertstrings_list[vertstrings_count++] = "\n";
1659                         geomstrings_list[geomstrings_count++] = "\n";
1660                         fragstrings_list[fragstrings_count++] = "\n";
1661                 }
1662         }
1663
1664         // add static parms
1665         R_CompileShader_AddStaticParms(mode, permutation);
1666         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667         vertstrings_count += shaderstaticparms_count;
1668         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1669         geomstrings_count += shaderstaticparms_count;
1670         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1671         fragstrings_count += shaderstaticparms_count;
1672
1673         // replace spaces in the cachename with _ characters
1674         for (i = 0;cachename[i];i++)
1675                 if (cachename[i] == ' ')
1676                         cachename[i] = '_';
1677
1678         // now append the shader text itself
1679         vertstrings_list[vertstrings_count++] = vertexstring;
1680         geomstrings_list[geomstrings_count++] = geometrystring;
1681         fragstrings_list[fragstrings_count++] = fragmentstring;
1682
1683         // if any sources were NULL, clear the respective list
1684         if (!vertexstring)
1685                 vertstrings_count = 0;
1686         if (!geometrystring)
1687                 geomstrings_count = 0;
1688         if (!fragmentstring)
1689                 fragstrings_count = 0;
1690
1691         vertstring_length = 0;
1692         for (i = 0;i < vertstrings_count;i++)
1693                 vertstring_length += strlen(vertstrings_list[i]);
1694         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1695         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1696                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1697
1698         geomstring_length = 0;
1699         for (i = 0;i < geomstrings_count;i++)
1700                 geomstring_length += strlen(geomstrings_list[i]);
1701         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1702         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1703                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1704
1705         fragstring_length = 0;
1706         for (i = 0;i < fragstrings_count;i++)
1707                 fragstring_length += strlen(fragstrings_list[i]);
1708         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1709         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1710                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1711
1712         // try to load the cached shader, or generate one
1713         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1714
1715         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1716                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1717         else
1718                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1719
1720         // free the strings
1721         if (vertstring)
1722                 Mem_Free(vertstring);
1723         if (geomstring)
1724                 Mem_Free(geomstring);
1725         if (fragstring)
1726                 Mem_Free(fragstring);
1727         if (vertexstring)
1728                 Mem_Free(vertexstring);
1729         if (geometrystring)
1730                 Mem_Free(geometrystring);
1731         if (fragmentstring)
1732                 Mem_Free(fragmentstring);
1733 }
1734
1735 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1736 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1737 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);}
1738 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);}
1739 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);}
1740 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);}
1741
1742 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1743 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1744 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);}
1745 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);}
1746 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);}
1747 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);}
1748
1749 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1750 {
1751         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1752         if (r_hlsl_permutation != perm)
1753         {
1754                 r_hlsl_permutation = perm;
1755                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1756                 {
1757                         if (!r_hlsl_permutation->compiled)
1758                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1759                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1760                         {
1761                                 // remove features until we find a valid permutation
1762                                 int i;
1763                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1764                                 {
1765                                         // reduce i more quickly whenever it would not remove any bits
1766                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1767                                         if (!(permutation & j))
1768                                                 continue;
1769                                         permutation -= j;
1770                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1771                                         if (!r_hlsl_permutation->compiled)
1772                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1773                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1774                                                 break;
1775                                 }
1776                                 if (i >= SHADERPERMUTATION_COUNT)
1777                                 {
1778                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1779                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1780                                         return; // no bit left to clear, entire mode is broken
1781                                 }
1782                         }
1783                 }
1784                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1785                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1786         }
1787         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1788         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1789         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1790 }
1791 #endif
1792
1793 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1794 {
1795         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1796         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1797         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1798         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1799 }
1800
1801 void R_GLSL_Restart_f(void)
1802 {
1803         unsigned int i, limit;
1804         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1805                 Mem_Free(glslshaderstring);
1806         glslshaderstring = NULL;
1807         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1808                 Mem_Free(hlslshaderstring);
1809         hlslshaderstring = NULL;
1810         switch(vid.renderpath)
1811         {
1812         case RENDERPATH_D3D9:
1813 #ifdef SUPPORTD3D
1814                 {
1815                         r_hlsl_permutation_t *p;
1816                         r_hlsl_permutation = NULL;
1817                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1818                         for (i = 0;i < limit;i++)
1819                         {
1820                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1821                                 {
1822                                         if (p->vertexshader)
1823                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1824                                         if (p->pixelshader)
1825                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1826                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1827                                 }
1828                         }
1829                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1830                 }
1831 #endif
1832                 break;
1833         case RENDERPATH_D3D10:
1834                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1835                 break;
1836         case RENDERPATH_D3D11:
1837                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1838                 break;
1839         case RENDERPATH_GL20:
1840         case RENDERPATH_GLES2:
1841                 {
1842                         r_glsl_permutation_t *p;
1843                         r_glsl_permutation = NULL;
1844                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1845                         for (i = 0;i < limit;i++)
1846                         {
1847                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1848                                 {
1849                                         GL_Backend_FreeProgram(p->program);
1850                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1851                                 }
1852                         }
1853                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1854                 }
1855                 break;
1856         case RENDERPATH_GL11:
1857         case RENDERPATH_GL13:
1858         case RENDERPATH_GLES1:
1859                 break;
1860         case RENDERPATH_SOFT:
1861                 break;
1862         }
1863 }
1864
1865 void R_GLSL_DumpShader_f(void)
1866 {
1867         int i;
1868         qfile_t *file;
1869
1870         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1871         if (file)
1872         {
1873                 FS_Print(file, "/* The engine may define the following macros:\n");
1874                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1875                 for (i = 0;i < SHADERMODE_COUNT;i++)
1876                         FS_Print(file, glslshadermodeinfo[i].pretext);
1877                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1878                         FS_Print(file, shaderpermutationinfo[i].pretext);
1879                 FS_Print(file, "*/\n");
1880                 FS_Print(file, builtinshaderstring);
1881                 FS_Close(file);
1882                 Con_Printf("glsl/default.glsl written\n");
1883         }
1884         else
1885                 Con_Printf("failed to write to glsl/default.glsl\n");
1886
1887         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1888         if (file)
1889         {
1890                 FS_Print(file, "/* The engine may define the following macros:\n");
1891                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1892                 for (i = 0;i < SHADERMODE_COUNT;i++)
1893                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1894                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1895                         FS_Print(file, shaderpermutationinfo[i].pretext);
1896                 FS_Print(file, "*/\n");
1897                 FS_Print(file, builtinhlslshaderstring);
1898                 FS_Close(file);
1899                 Con_Printf("hlsl/default.hlsl written\n");
1900         }
1901         else
1902                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1903 }
1904
1905 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1906 {
1907         if (!second)
1908                 texturemode = GL_MODULATE;
1909         switch (vid.renderpath)
1910         {
1911         case RENDERPATH_D3D9:
1912 #ifdef SUPPORTD3D
1913                 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))));
1914                 R_Mesh_TexBind(GL20TU_FIRST , first );
1915                 R_Mesh_TexBind(GL20TU_SECOND, second);
1916 #endif
1917                 break;
1918         case RENDERPATH_D3D10:
1919                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1920                 break;
1921         case RENDERPATH_D3D11:
1922                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1923                 break;
1924         case RENDERPATH_GL20:
1925         case RENDERPATH_GLES2:
1926                 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))));
1927                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1928                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1929                 break;
1930         case RENDERPATH_GL13:
1931         case RENDERPATH_GLES1:
1932                 R_Mesh_TexBind(0, first );
1933                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1934                 R_Mesh_TexBind(1, second);
1935                 if (second)
1936                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1937                 break;
1938         case RENDERPATH_GL11:
1939                 R_Mesh_TexBind(0, first );
1940                 break;
1941         case RENDERPATH_SOFT:
1942                 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))));
1943                 R_Mesh_TexBind(GL20TU_FIRST , first );
1944                 R_Mesh_TexBind(GL20TU_SECOND, second);
1945                 break;
1946         }
1947 }
1948
1949 void R_SetupShader_DepthOrShadow(void)
1950 {
1951         switch (vid.renderpath)
1952         {
1953         case RENDERPATH_D3D9:
1954 #ifdef SUPPORTD3D
1955                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1956 #endif
1957                 break;
1958         case RENDERPATH_D3D10:
1959                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1960                 break;
1961         case RENDERPATH_D3D11:
1962                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1963                 break;
1964         case RENDERPATH_GL20:
1965         case RENDERPATH_GLES2:
1966                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1967                 break;
1968         case RENDERPATH_GL13:
1969         case RENDERPATH_GLES1:
1970                 R_Mesh_TexBind(0, 0);
1971                 R_Mesh_TexBind(1, 0);
1972                 break;
1973         case RENDERPATH_GL11:
1974                 R_Mesh_TexBind(0, 0);
1975                 break;
1976         case RENDERPATH_SOFT:
1977                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1978                 break;
1979         }
1980 }
1981
1982 void R_SetupShader_ShowDepth(void)
1983 {
1984         switch (vid.renderpath)
1985         {
1986         case RENDERPATH_D3D9:
1987 #ifdef SUPPORTHLSL
1988                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1989 #endif
1990                 break;
1991         case RENDERPATH_D3D10:
1992                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1993                 break;
1994         case RENDERPATH_D3D11:
1995                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1996                 break;
1997         case RENDERPATH_GL20:
1998         case RENDERPATH_GLES2:
1999                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
2000                 break;
2001         case RENDERPATH_GL13:
2002         case RENDERPATH_GLES1:
2003                 break;
2004         case RENDERPATH_GL11:
2005                 break;
2006         case RENDERPATH_SOFT:
2007                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2008                 break;
2009         }
2010 }
2011
2012 extern qboolean r_shadow_usingdeferredprepass;
2013 extern cvar_t r_shadow_deferred_8bitrange;
2014 extern rtexture_t *r_shadow_attenuationgradienttexture;
2015 extern rtexture_t *r_shadow_attenuation2dtexture;
2016 extern rtexture_t *r_shadow_attenuation3dtexture;
2017 extern qboolean r_shadow_usingshadowmap2d;
2018 extern qboolean r_shadow_usingshadowmaportho;
2019 extern float r_shadow_shadowmap_texturescale[2];
2020 extern float r_shadow_shadowmap_parameters[4];
2021 extern qboolean r_shadow_shadowmapvsdct;
2022 extern qboolean r_shadow_shadowmapsampler;
2023 extern int r_shadow_shadowmappcf;
2024 extern rtexture_t *r_shadow_shadowmap2dtexture;
2025 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2026 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2027 extern matrix4x4_t r_shadow_shadowmapmatrix;
2028 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2029 extern int r_shadow_prepass_width;
2030 extern int r_shadow_prepass_height;
2031 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2032 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2033 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2034 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2035 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2036
2037 #define BLENDFUNC_ALLOWS_COLORMOD      1
2038 #define BLENDFUNC_ALLOWS_FOG           2
2039 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2040 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2041 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2042 static int R_BlendFuncFlags(int src, int dst)
2043 {
2044         int r = 0;
2045
2046         // a blendfunc allows colormod if:
2047         // a) it can never keep the destination pixel invariant, or
2048         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2049         // this is to prevent unintended side effects from colormod
2050
2051         // a blendfunc allows fog if:
2052         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2053         // this is to prevent unintended side effects from fog
2054
2055         // these checks are the output of fogeval.pl
2056
2057         r |= BLENDFUNC_ALLOWS_COLORMOD;
2058         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2059         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2060         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2062         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2063         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2064         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2065         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2066         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2067         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2068         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2069         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2070         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2071         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2072         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2073         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2074         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2075         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2076         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2077         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2078         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2079
2080         return r;
2081 }
2082
2083 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)
2084 {
2085         // select a permutation of the lighting shader appropriate to this
2086         // combination of texture, entity, light source, and fogging, only use the
2087         // minimum features necessary to avoid wasting rendering time in the
2088         // fragment shader on features that are not being used
2089         unsigned int permutation = 0;
2090         unsigned int mode = 0;
2091         int blendfuncflags;
2092         static float dummy_colormod[3] = {1, 1, 1};
2093         float *colormod = rsurface.colormod;
2094         float m16f[16];
2095         matrix4x4_t tempmatrix;
2096         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2097         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2098                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2099         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2100                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2101         if (rsurfacepass == RSURFPASS_BACKGROUND)
2102         {
2103                 // distorted background
2104                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2105                 {
2106                         mode = SHADERMODE_WATER;
2107                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2108                         {
2109                                 // this is the right thing to do for wateralpha
2110                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2111                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2112                         }
2113                         else
2114                         {
2115                                 // this is the right thing to do for entity alpha
2116                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2117                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2118                         }
2119                 }
2120                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2121                 {
2122                         mode = SHADERMODE_REFRACTION;
2123                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2124                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2125                 }
2126                 else
2127                 {
2128                         mode = SHADERMODE_GENERIC;
2129                         permutation |= SHADERPERMUTATION_DIFFUSE;
2130                         GL_BlendFunc(GL_ONE, GL_ZERO);
2131                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2132                 }
2133         }
2134         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2135         {
2136                 if (r_glsl_offsetmapping.integer)
2137                 {
2138                         switch(rsurface.texture->offsetmapping)
2139                         {
2140                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2141                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2142                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2143                         case OFFSETMAPPING_OFF: break;
2144                         }
2145                 }
2146                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2147                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2148                 // normalmap (deferred prepass), may use alpha test on diffuse
2149                 mode = SHADERMODE_DEFERREDGEOMETRY;
2150                 GL_BlendFunc(GL_ONE, GL_ZERO);
2151                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2152         }
2153         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2154         {
2155                 if (r_glsl_offsetmapping.integer)
2156                 {
2157                         switch(rsurface.texture->offsetmapping)
2158                         {
2159                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2160                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2161                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2162                         case OFFSETMAPPING_OFF: break;
2163                         }
2164                 }
2165                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2166                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2167                 // light source
2168                 mode = SHADERMODE_LIGHTSOURCE;
2169                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2170                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2171                 if (diffusescale > 0)
2172                         permutation |= SHADERPERMUTATION_DIFFUSE;
2173                 if (specularscale > 0)
2174                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2175                 if (r_refdef.fogenabled)
2176                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2177                 if (rsurface.texture->colormapping)
2178                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2179                 if (r_shadow_usingshadowmap2d)
2180                 {
2181                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2182                         if(r_shadow_shadowmapvsdct)
2183                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2184
2185                         if (r_shadow_shadowmapsampler)
2186                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2187                         if (r_shadow_shadowmappcf > 1)
2188                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2189                         else if (r_shadow_shadowmappcf)
2190                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2191                 }
2192                 if (rsurface.texture->reflectmasktexture)
2193                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2194                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2195                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2196         }
2197         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2198         {
2199                 if (r_glsl_offsetmapping.integer)
2200                 {
2201                         switch(rsurface.texture->offsetmapping)
2202                         {
2203                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2204                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2205                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2206                         case OFFSETMAPPING_OFF: break;
2207                         }
2208                 }
2209                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2210                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2211                 // unshaded geometry (fullbright or ambient model lighting)
2212                 mode = SHADERMODE_FLATCOLOR;
2213                 ambientscale = diffusescale = specularscale = 0;
2214                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2215                         permutation |= SHADERPERMUTATION_GLOW;
2216                 if (r_refdef.fogenabled)
2217                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2218                 if (rsurface.texture->colormapping)
2219                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2220                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2221                 {
2222                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2223                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2224
2225                         if (r_shadow_shadowmapsampler)
2226                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2227                         if (r_shadow_shadowmappcf > 1)
2228                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2229                         else if (r_shadow_shadowmappcf)
2230                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2231                 }
2232                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2233                         permutation |= SHADERPERMUTATION_REFLECTION;
2234                 if (rsurface.texture->reflectmasktexture)
2235                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2236                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2237                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2238         }
2239         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2240         {
2241                 if (r_glsl_offsetmapping.integer)
2242                 {
2243                         switch(rsurface.texture->offsetmapping)
2244                         {
2245                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2246                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2247                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2248                         case OFFSETMAPPING_OFF: break;
2249                         }
2250                 }
2251                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2252                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2253                 // directional model lighting
2254                 mode = SHADERMODE_LIGHTDIRECTION;
2255                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2256                         permutation |= SHADERPERMUTATION_GLOW;
2257                 permutation |= SHADERPERMUTATION_DIFFUSE;
2258                 if (specularscale > 0)
2259                         permutation |= SHADERPERMUTATION_SPECULAR;
2260                 if (r_refdef.fogenabled)
2261                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2262                 if (rsurface.texture->colormapping)
2263                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2264                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2265                 {
2266                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2267                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2268
2269                         if (r_shadow_shadowmapsampler)
2270                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2271                         if (r_shadow_shadowmappcf > 1)
2272                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2273                         else if (r_shadow_shadowmappcf)
2274                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2275                 }
2276                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2277                         permutation |= SHADERPERMUTATION_REFLECTION;
2278                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2279                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2280                 if (rsurface.texture->reflectmasktexture)
2281                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2282                 if (r_shadow_bouncegridtexture)
2283                 {
2284                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2285                         if (r_shadow_bouncegriddirectional)
2286                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2287                 }
2288                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2289                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2290         }
2291         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2292         {
2293                 if (r_glsl_offsetmapping.integer)
2294                 {
2295                         switch(rsurface.texture->offsetmapping)
2296                         {
2297                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2298                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2299                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2300                         case OFFSETMAPPING_OFF: break;
2301                         }
2302                 }
2303                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2304                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2305                 // ambient model lighting
2306                 mode = SHADERMODE_LIGHTDIRECTION;
2307                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2308                         permutation |= SHADERPERMUTATION_GLOW;
2309                 if (r_refdef.fogenabled)
2310                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2311                 if (rsurface.texture->colormapping)
2312                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2313                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2314                 {
2315                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2316                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2317
2318                         if (r_shadow_shadowmapsampler)
2319                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2320                         if (r_shadow_shadowmappcf > 1)
2321                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2322                         else if (r_shadow_shadowmappcf)
2323                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2324                 }
2325                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2326                         permutation |= SHADERPERMUTATION_REFLECTION;
2327                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2328                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2329                 if (rsurface.texture->reflectmasktexture)
2330                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2331                 if (r_shadow_bouncegridtexture)
2332                 {
2333                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2334                         if (r_shadow_bouncegriddirectional)
2335                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2336                 }
2337                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2338                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2339         }
2340         else
2341         {
2342                 if (r_glsl_offsetmapping.integer)
2343                 {
2344                         switch(rsurface.texture->offsetmapping)
2345                         {
2346                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2347                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2348                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349                         case OFFSETMAPPING_OFF: break;
2350                         }
2351                 }
2352                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2353                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2354                 // lightmapped wall
2355                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2356                         permutation |= SHADERPERMUTATION_GLOW;
2357                 if (r_refdef.fogenabled)
2358                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2359                 if (rsurface.texture->colormapping)
2360                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2361                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2362                 {
2363                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2364                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2365
2366                         if (r_shadow_shadowmapsampler)
2367                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2368                         if (r_shadow_shadowmappcf > 1)
2369                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2370                         else if (r_shadow_shadowmappcf)
2371                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2372                 }
2373                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2374                         permutation |= SHADERPERMUTATION_REFLECTION;
2375                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2376                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2377                 if (rsurface.texture->reflectmasktexture)
2378                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2379                 if (FAKELIGHT_ENABLED)
2380                 {
2381                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2382                         mode = SHADERMODE_FAKELIGHT;
2383                         permutation |= SHADERPERMUTATION_DIFFUSE;
2384                         if (specularscale > 0)
2385                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2386                 }
2387                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2388                 {
2389                         // deluxemapping (light direction texture)
2390                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2391                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2392                         else
2393                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2394                         permutation |= SHADERPERMUTATION_DIFFUSE;
2395                         if (specularscale > 0)
2396                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2397                 }
2398                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2399                 {
2400                         // fake deluxemapping (uniform light direction in tangentspace)
2401                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2402                         permutation |= SHADERPERMUTATION_DIFFUSE;
2403                         if (specularscale > 0)
2404                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2405                 }
2406                 else if (rsurface.uselightmaptexture)
2407                 {
2408                         // ordinary lightmapping (q1bsp, q3bsp)
2409                         mode = SHADERMODE_LIGHTMAP;
2410                 }
2411                 else
2412                 {
2413                         // ordinary vertex coloring (q3bsp)
2414                         mode = SHADERMODE_VERTEXCOLOR;
2415                 }
2416                 if (r_shadow_bouncegridtexture)
2417                 {
2418                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2419                         if (r_shadow_bouncegriddirectional)
2420                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2421                 }
2422                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2423                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2424         }
2425         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2426                 colormod = dummy_colormod;
2427         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2428                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2429         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2430                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2431         switch(vid.renderpath)
2432         {
2433         case RENDERPATH_D3D9:
2434 #ifdef SUPPORTD3D
2435                 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);
2436                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2437                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2438                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2439                 if (mode == SHADERMODE_LIGHTSOURCE)
2440                 {
2441                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2442                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2443                 }
2444                 else
2445                 {
2446                         if (mode == SHADERMODE_LIGHTDIRECTION)
2447                         {
2448                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2449                         }
2450                 }
2451                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2452                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2453                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2454                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2455                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2456
2457                 if (mode == SHADERMODE_LIGHTSOURCE)
2458                 {
2459                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2460                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2461                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2462                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2463                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2464
2465                         // additive passes are only darkened by fog, not tinted
2466                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2467                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2468                 }
2469                 else
2470                 {
2471                         if (mode == SHADERMODE_FLATCOLOR)
2472                         {
2473                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2474                         }
2475                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2476                         {
2477                                 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]);
2478                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2479                                 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);
2480                                 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);
2481                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2482                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2483                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2484                         }
2485                         else
2486                         {
2487                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2488                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2489                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2490                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2491                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2492                         }
2493                         // additive passes are only darkened by fog, not tinted
2494                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2495                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2496                         else
2497                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2498                         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);
2499                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2500                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2501                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2502                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2503                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2504                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2505                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2506                         if (mode == SHADERMODE_WATER)
2507                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2508                 }
2509                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2510                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2511                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2512                 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));
2513                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2514                 if (rsurface.texture->pantstexture)
2515                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2516                 else
2517                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2518                 if (rsurface.texture->shirttexture)
2519                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2520                 else
2521                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2522                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2523                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2524                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2525                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2526                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2527                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2528                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2529                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2530                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2531                         );
2532                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2533                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2534
2535                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2536                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2537                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2538                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2539                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2540                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2541                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2542                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2543                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2544                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2545                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2546                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2547                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2548                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2549                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2550                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2551                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2552                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2553                 {
2554                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2555                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2556                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2557                 }
2558                 else
2559                 {
2560                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2561                 }
2562 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2563 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2564                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2565                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2566                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2567                 {
2568                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2569                         if (rsurface.rtlight)
2570                         {
2571                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2572                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2573                         }
2574                 }
2575 #endif
2576                 break;
2577         case RENDERPATH_D3D10:
2578                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2579                 break;
2580         case RENDERPATH_D3D11:
2581                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2582                 break;
2583         case RENDERPATH_GL20:
2584         case RENDERPATH_GLES2:
2585                 if (!vid.useinterleavedarrays)
2586                 {
2587                         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);
2588                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2589                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2590                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2591                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2592                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2593                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2594                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2595                 }
2596                 else
2597                 {
2598                         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);
2599                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2600                 }
2601                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2602                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2603                 if (mode == SHADERMODE_LIGHTSOURCE)
2604                 {
2605                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2606                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2607                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2608                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2609                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2610                         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);
2611         
2612                         // additive passes are only darkened by fog, not tinted
2613                         if (r_glsl_permutation->loc_FogColor >= 0)
2614                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2615                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2616                 }
2617                 else
2618                 {
2619                         if (mode == SHADERMODE_FLATCOLOR)
2620                         {
2621                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2622                         }
2623                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2624                         {
2625                                 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]);
2626                                 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]);
2627                                 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);
2628                                 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);
2629                                 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);
2630                                 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]);
2631                                 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]);
2632                         }
2633                         else
2634                         {
2635                                 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]);
2636                                 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]);
2637                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2638                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2639                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2640                         }
2641                         // additive passes are only darkened by fog, not tinted
2642                         if (r_glsl_permutation->loc_FogColor >= 0)
2643                         {
2644                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2645                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2646                                 else
2647                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2648                         }
2649                         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);
2650                         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]);
2651                         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]);
2652                         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]);
2653                         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]);
2654                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2655                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2656                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2657                         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]);
2658                 }
2659                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2660                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2661                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2662                 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]);
2663                 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]);
2664
2665                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2666                 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));
2667                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2668                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2669                 {
2670                         if (rsurface.texture->pantstexture)
2671                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2672                         else
2673                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2674                 }
2675                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2676                 {
2677                         if (rsurface.texture->shirttexture)
2678                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2679                         else
2680                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2681                 }
2682                 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]);
2683                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2684                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2685                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2686                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2687                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2688                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2689                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2690                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2691                         );
2692                 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]);
2693                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2694                 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);}
2695                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2696
2697                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2698                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2699                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2700                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2701                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2702                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2703                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2704                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2705                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2706                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2707                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2708                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2709                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2710                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2711                 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);
2712                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2713                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2714                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2715                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2716                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2717                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2718                 {
2719                         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);
2720                         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);
2721                         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);
2722                 }
2723                 else
2724                 {
2725                         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);
2726                 }
2727                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2728                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2729                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2730                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2731                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2732                 {
2733                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2734                         if (rsurface.rtlight)
2735                         {
2736                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2737                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2738                         }
2739                 }
2740                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2741                 CHECKGLERROR
2742                 break;
2743         case RENDERPATH_GL11:
2744         case RENDERPATH_GL13:
2745         case RENDERPATH_GLES1:
2746                 break;
2747         case RENDERPATH_SOFT:
2748                 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);
2749                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2750                 R_SetupShader_SetPermutationSoft(mode, permutation);
2751                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2752                 if (mode == SHADERMODE_LIGHTSOURCE)
2753                 {
2754                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2755                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2756                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2757                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2758                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2759                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2760         
2761                         // additive passes are only darkened by fog, not tinted
2762                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2763                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2764                 }
2765                 else
2766                 {
2767                         if (mode == SHADERMODE_FLATCOLOR)
2768                         {
2769                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2770                         }
2771                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2772                         {
2773                                 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]);
2774                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2775                                 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);
2776                                 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);
2777                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2778                                 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]);
2779                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2780                         }
2781                         else
2782                         {
2783                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2784                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2785                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2786                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2787                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2788                         }
2789                         // additive passes are only darkened by fog, not tinted
2790                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2791                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2792                         else
2793                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2794                         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);
2795                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2796                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2797                         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]);
2798                         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]);
2799                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2800                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2801                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2802                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2803                 }
2804                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2805                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2806                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2807                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2808                 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]);
2809
2810                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2811                 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));
2812                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2813                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2814                 {
2815                         if (rsurface.texture->pantstexture)
2816                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2817                         else
2818                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2819                 }
2820                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2821                 {
2822                         if (rsurface.texture->shirttexture)
2823                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2824                         else
2825                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2826                 }
2827                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2828                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2829                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2830                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2831                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2832                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2833                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2834                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2835                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2836                         );
2837                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2838                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2839
2840                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2841                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2842                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2843                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2844                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2845                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2846                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2847                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2848                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2849                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2850                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2851                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2852                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2853                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2854                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2855                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2856                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2857                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2858                 {
2859                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2860                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2861                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2862                 }
2863                 else
2864                 {
2865                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2866                 }
2867 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2868 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2869                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2870                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2871                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2872                 {
2873                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2874                         if (rsurface.rtlight)
2875                         {
2876                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2877                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2878                         }
2879                 }
2880                 break;
2881         }
2882 }
2883
2884 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2885 {
2886         // select a permutation of the lighting shader appropriate to this
2887         // combination of texture, entity, light source, and fogging, only use the
2888         // minimum features necessary to avoid wasting rendering time in the
2889         // fragment shader on features that are not being used
2890         unsigned int permutation = 0;
2891         unsigned int mode = 0;
2892         const float *lightcolorbase = rtlight->currentcolor;
2893         float ambientscale = rtlight->ambientscale;
2894         float diffusescale = rtlight->diffusescale;
2895         float specularscale = rtlight->specularscale;
2896         // this is the location of the light in view space
2897         vec3_t viewlightorigin;
2898         // this transforms from view space (camera) to light space (cubemap)
2899         matrix4x4_t viewtolight;
2900         matrix4x4_t lighttoview;
2901         float viewtolight16f[16];
2902         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2903         // light source
2904         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2905         if (rtlight->currentcubemap != r_texture_whitecube)
2906                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2907         if (diffusescale > 0)
2908                 permutation |= SHADERPERMUTATION_DIFFUSE;
2909         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2910                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2911         if (r_shadow_usingshadowmap2d)
2912         {
2913                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2914                 if (r_shadow_shadowmapvsdct)
2915                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2916
2917                 if (r_shadow_shadowmapsampler)
2918                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2919                 if (r_shadow_shadowmappcf > 1)
2920                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2921                 else if (r_shadow_shadowmappcf)
2922                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2923         }
2924         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2925         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2926         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2927         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2928         switch(vid.renderpath)
2929         {
2930         case RENDERPATH_D3D9:
2931 #ifdef SUPPORTD3D
2932                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2933                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2934                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2935                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2936                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2937                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2938                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2939                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2940                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2941                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2942                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2943
2944                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2945                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2946                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2947                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2948                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2949                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2950 #endif
2951                 break;
2952         case RENDERPATH_D3D10:
2953                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2954                 break;
2955         case RENDERPATH_D3D11:
2956                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2957                 break;
2958         case RENDERPATH_GL20:
2959         case RENDERPATH_GLES2:
2960                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2961                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2962                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2963                 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);
2964                 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);
2965                 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);
2966                 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]);
2967                 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]);
2968                 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));
2969                 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]);
2970                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2971
2972                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2973                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2974                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2975                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2976                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2977                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2978                 break;
2979         case RENDERPATH_GL11:
2980         case RENDERPATH_GL13:
2981         case RENDERPATH_GLES1:
2982                 break;
2983         case RENDERPATH_SOFT:
2984                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2985                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2986                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2987                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2988                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2989                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2990                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2991                 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]);
2992                 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));
2993                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2994                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2995
2996                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2997                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2998                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2999                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3000                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3001                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3002                 break;
3003         }
3004 }
3005
3006 #define SKINFRAME_HASH 1024
3007
3008 typedef struct
3009 {
3010         int loadsequence; // incremented each level change
3011         memexpandablearray_t array;
3012         skinframe_t *hash[SKINFRAME_HASH];
3013 }
3014 r_skinframe_t;
3015 r_skinframe_t r_skinframe;
3016
3017 void R_SkinFrame_PrepareForPurge(void)
3018 {
3019         r_skinframe.loadsequence++;
3020         // wrap it without hitting zero
3021         if (r_skinframe.loadsequence >= 200)
3022                 r_skinframe.loadsequence = 1;
3023 }
3024
3025 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3026 {
3027         if (!skinframe)
3028                 return;
3029         // mark the skinframe as used for the purging code
3030         skinframe->loadsequence = r_skinframe.loadsequence;
3031 }
3032
3033 void R_SkinFrame_Purge(void)
3034 {
3035         int i;
3036         skinframe_t *s;
3037         for (i = 0;i < SKINFRAME_HASH;i++)
3038         {
3039                 for (s = r_skinframe.hash[i];s;s = s->next)
3040                 {
3041                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3042                         {
3043                                 if (s->merged == s->base)
3044                                         s->merged = NULL;
3045                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3046                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3047                                 R_PurgeTexture(s->merged);s->merged = NULL;
3048                                 R_PurgeTexture(s->base  );s->base   = NULL;
3049                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3050                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3051                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3052                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3053                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3054                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3055                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3056                                 s->loadsequence = 0;
3057                         }
3058                 }
3059         }
3060 }
3061
3062 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3063         skinframe_t *item;
3064         char basename[MAX_QPATH];
3065
3066         Image_StripImageExtension(name, basename, sizeof(basename));
3067
3068         if( last == NULL ) {
3069                 int hashindex;
3070                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3071                 item = r_skinframe.hash[hashindex];
3072         } else {
3073                 item = last->next;
3074         }
3075
3076         // linearly search through the hash bucket
3077         for( ; item ; item = item->next ) {
3078                 if( !strcmp( item->basename, basename ) ) {
3079                         return item;
3080                 }
3081         }
3082         return NULL;
3083 }
3084
3085 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3086 {
3087         skinframe_t *item;
3088         int hashindex;
3089         char basename[MAX_QPATH];
3090
3091         Image_StripImageExtension(name, basename, sizeof(basename));
3092
3093         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3094         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3095                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3096                         break;
3097
3098         if (!item) {
3099                 rtexture_t *dyntexture;
3100                 // check whether its a dynamic texture
3101                 dyntexture = CL_GetDynTexture( basename );
3102                 if (!add && !dyntexture)
3103                         return NULL;
3104                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3105                 memset(item, 0, sizeof(*item));
3106                 strlcpy(item->basename, basename, sizeof(item->basename));
3107                 item->base = dyntexture; // either NULL or dyntexture handle
3108                 item->textureflags = textureflags;
3109                 item->comparewidth = comparewidth;
3110                 item->compareheight = compareheight;
3111                 item->comparecrc = comparecrc;
3112                 item->next = r_skinframe.hash[hashindex];
3113                 r_skinframe.hash[hashindex] = item;
3114         }
3115         else if( item->base == NULL )
3116         {
3117                 rtexture_t *dyntexture;
3118                 // check whether its a dynamic texture
3119                 // 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]
3120                 dyntexture = CL_GetDynTexture( basename );
3121                 item->base = dyntexture; // either NULL or dyntexture handle
3122         }
3123
3124         R_SkinFrame_MarkUsed(item);
3125         return item;
3126 }
3127
3128 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3129         { \
3130                 unsigned long long avgcolor[5], wsum; \
3131                 int pix, comp, w; \
3132                 avgcolor[0] = 0; \
3133                 avgcolor[1] = 0; \
3134                 avgcolor[2] = 0; \
3135                 avgcolor[3] = 0; \
3136                 avgcolor[4] = 0; \
3137                 wsum = 0; \
3138                 for(pix = 0; pix < cnt; ++pix) \
3139                 { \
3140                         w = 0; \
3141                         for(comp = 0; comp < 3; ++comp) \
3142                                 w += getpixel; \
3143                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3144                         { \
3145                                 ++wsum; \
3146                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3147                                 w = getpixel; \
3148                                 for(comp = 0; comp < 3; ++comp) \
3149                                         avgcolor[comp] += getpixel * w; \
3150                                 avgcolor[3] += w; \
3151                         } \
3152                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3153                         avgcolor[4] += getpixel; \
3154                 } \
3155                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3156                         avgcolor[3] = 1; \
3157                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3158                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3159                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3160                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3161         }
3162
3163 extern cvar_t gl_picmip;
3164 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3165 {
3166         int j;
3167         unsigned char *pixels;
3168         unsigned char *bumppixels;
3169         unsigned char *basepixels = NULL;
3170         int basepixels_width = 0;
3171         int basepixels_height = 0;
3172         skinframe_t *skinframe;
3173         rtexture_t *ddsbase = NULL;
3174         qboolean ddshasalpha = false;
3175         float ddsavgcolor[4];
3176         char basename[MAX_QPATH];
3177         int miplevel = R_PicmipForFlags(textureflags);
3178         int savemiplevel = miplevel;
3179         int mymiplevel;
3180
3181         if (cls.state == ca_dedicated)
3182                 return NULL;
3183
3184         // return an existing skinframe if already loaded
3185         // if loading of the first image fails, don't make a new skinframe as it
3186         // would cause all future lookups of this to be missing
3187         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3188         if (skinframe && skinframe->base)
3189                 return skinframe;
3190
3191         Image_StripImageExtension(name, basename, sizeof(basename));
3192
3193         // check for DDS texture file first
3194         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3195         {
3196                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3197                 if (basepixels == NULL)
3198                         return NULL;
3199         }
3200
3201         // FIXME handle miplevel
3202
3203         if (developer_loading.integer)
3204                 Con_Printf("loading skin \"%s\"\n", name);
3205
3206         // we've got some pixels to store, so really allocate this new texture now
3207         if (!skinframe)
3208                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3209         skinframe->stain = NULL;
3210         skinframe->merged = NULL;
3211         skinframe->base = NULL;
3212         skinframe->pants = NULL;
3213         skinframe->shirt = NULL;
3214         skinframe->nmap = NULL;
3215         skinframe->gloss = NULL;
3216         skinframe->glow = NULL;
3217         skinframe->fog = NULL;
3218         skinframe->reflect = NULL;
3219         skinframe->hasalpha = false;
3220
3221         if (ddsbase)
3222         {
3223                 skinframe->base = ddsbase;
3224                 skinframe->hasalpha = ddshasalpha;
3225                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3226                 if (r_loadfog && skinframe->hasalpha)
3227                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3228                 //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]);
3229         }
3230         else
3231         {
3232                 basepixels_width = image_width;
3233                 basepixels_height = image_height;
3234                 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);
3235                 if (textureflags & TEXF_ALPHA)
3236                 {
3237                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3238                         {
3239                                 if (basepixels[j] < 255)
3240                                 {
3241                                         skinframe->hasalpha = true;
3242                                         break;
3243                                 }
3244                         }
3245                         if (r_loadfog && skinframe->hasalpha)
3246                         {
3247                                 // has transparent pixels
3248                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3249                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3250                                 {
3251                                         pixels[j+0] = 255;
3252                                         pixels[j+1] = 255;
3253                                         pixels[j+2] = 255;
3254                                         pixels[j+3] = basepixels[j+3];
3255                                 }
3256                                 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);
3257                                 Mem_Free(pixels);
3258                         }
3259                 }
3260                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3261                 //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]);
3262                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3263                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3264                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3265                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3266         }
3267
3268         if (r_loaddds)
3269         {
3270                 mymiplevel = savemiplevel;
3271                 if (r_loadnormalmap)
3272                         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);
3273                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3274                 if (r_loadgloss)
3275                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3276                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3277                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3278                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3279         }
3280
3281         // _norm is the name used by tenebrae and has been adopted as standard
3282         if (r_loadnormalmap && skinframe->nmap == NULL)
3283         {
3284                 mymiplevel = savemiplevel;
3285                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3286                 {
3287                         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);
3288                         Mem_Free(pixels);
3289                         pixels = NULL;
3290                 }
3291                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3292                 {
3293                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3294                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3295                         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);
3296                         Mem_Free(pixels);
3297                         Mem_Free(bumppixels);
3298                 }
3299                 else if (r_shadow_bumpscale_basetexture.value > 0)
3300                 {
3301                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3302                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3303                         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);
3304                         Mem_Free(pixels);
3305                 }
3306                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3307                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3308         }
3309
3310         // _luma is supported only for tenebrae compatibility
3311         // _glow is the preferred name
3312         mymiplevel = savemiplevel;
3313         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))))
3314         {
3315                 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);
3316                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3317                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3318                 Mem_Free(pixels);pixels = NULL;
3319         }
3320
3321         mymiplevel = savemiplevel;
3322         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3323         {
3324                 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);
3325                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3326                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3327                 Mem_Free(pixels);
3328                 pixels = NULL;
3329         }
3330
3331         mymiplevel = savemiplevel;
3332         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3333         {
3334                 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);
3335                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3336                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3337                 Mem_Free(pixels);
3338                 pixels = NULL;
3339         }
3340
3341         mymiplevel = savemiplevel;
3342         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3343         {
3344                 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);
3345                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3346                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3347                 Mem_Free(pixels);
3348                 pixels = NULL;
3349         }
3350
3351         mymiplevel = savemiplevel;
3352         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3353         {
3354                 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);
3355                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3356                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3357                 Mem_Free(pixels);
3358                 pixels = NULL;
3359         }
3360
3361         if (basepixels)
3362                 Mem_Free(basepixels);
3363
3364         return skinframe;
3365 }
3366
3367 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3368 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3369 {
3370         int i;
3371         unsigned char *temp1, *temp2;
3372         skinframe_t *skinframe;
3373
3374         if (cls.state == ca_dedicated)
3375                 return NULL;
3376
3377         // if already loaded just return it, otherwise make a new skinframe
3378         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3379         if (skinframe && skinframe->base)
3380                 return skinframe;
3381
3382         skinframe->stain = NULL;
3383         skinframe->merged = NULL;
3384         skinframe->base = NULL;
3385         skinframe->pants = NULL;
3386         skinframe->shirt = NULL;
3387         skinframe->nmap = NULL;
3388         skinframe->gloss = NULL;
3389         skinframe->glow = NULL;
3390         skinframe->fog = NULL;
3391         skinframe->reflect = NULL;
3392         skinframe->hasalpha = false;
3393
3394         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3395         if (!skindata)
3396                 return NULL;
3397
3398         if (developer_loading.integer)
3399                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3400
3401         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3402         {
3403                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3404                 temp2 = temp1 + width * height * 4;
3405                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3406                 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);
3407                 Mem_Free(temp1);
3408         }
3409         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3410         if (textureflags & TEXF_ALPHA)
3411         {
3412                 for (i = 3;i < width * height * 4;i += 4)
3413                 {
3414                         if (skindata[i] < 255)
3415                         {
3416                                 skinframe->hasalpha = true;
3417                                 break;
3418                         }
3419                 }
3420                 if (r_loadfog && skinframe->hasalpha)
3421                 {
3422                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3423                         memcpy(fogpixels, skindata, width * height * 4);
3424                         for (i = 0;i < width * height * 4;i += 4)
3425                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3426                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3427                         Mem_Free(fogpixels);
3428                 }
3429         }
3430
3431         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3432         //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]);
3433
3434         return skinframe;
3435 }
3436
3437 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3438 {
3439         int i;
3440         int featuresmask;
3441         skinframe_t *skinframe;
3442
3443         if (cls.state == ca_dedicated)
3444                 return NULL;
3445
3446         // if already loaded just return it, otherwise make a new skinframe
3447         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3448         if (skinframe && skinframe->base)
3449                 return skinframe;
3450
3451         skinframe->stain = NULL;
3452         skinframe->merged = NULL;
3453         skinframe->base = NULL;
3454         skinframe->pants = NULL;
3455         skinframe->shirt = NULL;
3456         skinframe->nmap = NULL;
3457         skinframe->gloss = NULL;
3458         skinframe->glow = NULL;
3459         skinframe->fog = NULL;
3460         skinframe->reflect = NULL;
3461         skinframe->hasalpha = false;
3462
3463         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3464         if (!skindata)
3465                 return NULL;
3466
3467         if (developer_loading.integer)
3468                 Con_Printf("loading quake skin \"%s\"\n", name);
3469
3470         // 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)
3471         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3472         memcpy(skinframe->qpixels, skindata, width*height);
3473         skinframe->qwidth = width;
3474         skinframe->qheight = height;
3475
3476         featuresmask = 0;
3477         for (i = 0;i < width * height;i++)
3478                 featuresmask |= palette_featureflags[skindata[i]];
3479
3480         skinframe->hasalpha = false;
3481         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3482         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3483         skinframe->qgeneratemerged = true;
3484         skinframe->qgeneratebase = skinframe->qhascolormapping;
3485         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3486
3487         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3488         //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]);
3489
3490         return skinframe;
3491 }
3492
3493 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3494 {
3495         int width;
3496         int height;
3497         unsigned char *skindata;
3498
3499         if (!skinframe->qpixels)
3500                 return;
3501
3502         if (!skinframe->qhascolormapping)
3503                 colormapped = false;
3504
3505         if (colormapped)
3506         {
3507                 if (!skinframe->qgeneratebase)
3508                         return;
3509         }
3510         else
3511         {
3512                 if (!skinframe->qgeneratemerged)
3513                         return;
3514         }
3515
3516         width = skinframe->qwidth;
3517         height = skinframe->qheight;
3518         skindata = skinframe->qpixels;
3519
3520         if (skinframe->qgeneratenmap)
3521         {
3522                 unsigned char *temp1, *temp2;
3523                 skinframe->qgeneratenmap = false;
3524                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3525                 temp2 = temp1 + width * height * 4;
3526                 // use either a custom palette or the quake palette
3527                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3528                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3529                 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);
3530                 Mem_Free(temp1);
3531         }
3532
3533         if (skinframe->qgenerateglow)
3534         {
3535                 skinframe->qgenerateglow = false;
3536                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3537         }
3538
3539         if (colormapped)
3540         {
3541                 skinframe->qgeneratebase = false;
3542                 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);
3543                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3544                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3545         }
3546         else
3547         {
3548                 skinframe->qgeneratemerged = false;
3549                 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);
3550         }
3551
3552         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3553         {
3554                 Mem_Free(skinframe->qpixels);
3555                 skinframe->qpixels = NULL;
3556         }
3557 }
3558
3559 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)
3560 {
3561         int i;
3562         skinframe_t *skinframe;
3563
3564         if (cls.state == ca_dedicated)
3565                 return NULL;
3566
3567         // if already loaded just return it, otherwise make a new skinframe
3568         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3569         if (skinframe && skinframe->base)
3570                 return skinframe;
3571
3572         skinframe->stain = NULL;
3573         skinframe->merged = NULL;
3574         skinframe->base = NULL;
3575         skinframe->pants = NULL;
3576         skinframe->shirt = NULL;
3577         skinframe->nmap = NULL;
3578         skinframe->gloss = NULL;
3579         skinframe->glow = NULL;
3580         skinframe->fog = NULL;
3581         skinframe->reflect = NULL;
3582         skinframe->hasalpha = false;
3583
3584         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3585         if (!skindata)
3586                 return NULL;
3587
3588         if (developer_loading.integer)
3589                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3590
3591         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3592         if (textureflags & TEXF_ALPHA)
3593         {
3594                 for (i = 0;i < width * height;i++)
3595                 {
3596                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3597                         {
3598                                 skinframe->hasalpha = true;
3599                                 break;
3600                         }
3601                 }
3602                 if (r_loadfog && skinframe->hasalpha)
3603                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3604         }
3605
3606         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3607         //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]);
3608
3609         return skinframe;
3610 }
3611
3612 skinframe_t *R_SkinFrame_LoadMissing(void)
3613 {
3614         skinframe_t *skinframe;
3615
3616         if (cls.state == ca_dedicated)
3617                 return NULL;
3618
3619         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3620         skinframe->stain = NULL;
3621         skinframe->merged = NULL;
3622         skinframe->base = NULL;
3623         skinframe->pants = NULL;
3624         skinframe->shirt = NULL;
3625         skinframe->nmap = NULL;
3626         skinframe->gloss = NULL;
3627         skinframe->glow = NULL;
3628         skinframe->fog = NULL;
3629         skinframe->reflect = NULL;
3630         skinframe->hasalpha = false;
3631
3632         skinframe->avgcolor[0] = rand() / RAND_MAX;
3633         skinframe->avgcolor[1] = rand() / RAND_MAX;
3634         skinframe->avgcolor[2] = rand() / RAND_MAX;
3635         skinframe->avgcolor[3] = 1;
3636
3637         return skinframe;
3638 }
3639
3640 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3641 typedef struct suffixinfo_s
3642 {
3643         const char *suffix;
3644         qboolean flipx, flipy, flipdiagonal;
3645 }
3646 suffixinfo_t;
3647 static suffixinfo_t suffix[3][6] =
3648 {
3649         {
3650                 {"px",   false, false, false},
3651                 {"nx",   false, false, false},
3652                 {"py",   false, false, false},
3653                 {"ny",   false, false, false},
3654                 {"pz",   false, false, false},
3655                 {"nz",   false, false, false}
3656         },
3657         {
3658                 {"posx", false, false, false},
3659                 {"negx", false, false, false},
3660                 {"posy", false, false, false},
3661                 {"negy", false, false, false},
3662                 {"posz", false, false, false},
3663                 {"negz", false, false, false}
3664         },
3665         {
3666                 {"rt",    true, false,  true},
3667                 {"lf",   false,  true,  true},
3668                 {"ft",    true,  true, false},
3669                 {"bk",   false, false, false},
3670                 {"up",    true, false,  true},
3671                 {"dn",    true, false,  true}
3672         }
3673 };
3674
3675 static int componentorder[4] = {0, 1, 2, 3};
3676
3677 rtexture_t *R_LoadCubemap(const char *basename)
3678 {
3679         int i, j, cubemapsize;
3680         unsigned char *cubemappixels, *image_buffer;
3681         rtexture_t *cubemaptexture;
3682         char name[256];
3683         // must start 0 so the first loadimagepixels has no requested width/height
3684         cubemapsize = 0;
3685         cubemappixels = NULL;
3686         cubemaptexture = NULL;
3687         // keep trying different suffix groups (posx, px, rt) until one loads
3688         for (j = 0;j < 3 && !cubemappixels;j++)
3689         {
3690                 // load the 6 images in the suffix group
3691                 for (i = 0;i < 6;i++)
3692                 {
3693                         // generate an image name based on the base and and suffix
3694                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3695                         // load it
3696                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3697                         {
3698                                 // an image loaded, make sure width and height are equal
3699                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3700                                 {
3701                                         // if this is the first image to load successfully, allocate the cubemap memory
3702                                         if (!cubemappixels && image_width >= 1)
3703                                         {
3704                                                 cubemapsize = image_width;
3705                                                 // note this clears to black, so unavailable sides are black
3706                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3707                                         }
3708                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3709                                         if (cubemappixels)
3710                                                 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);
3711                                 }
3712                                 else
3713                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3714                                 // free the image
3715                                 Mem_Free(image_buffer);
3716                         }
3717                 }
3718         }
3719         // if a cubemap loaded, upload it
3720         if (cubemappixels)
3721         {
3722                 if (developer_loading.integer)
3723                         Con_Printf("loading cubemap \"%s\"\n", basename);
3724
3725                 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);
3726                 Mem_Free(cubemappixels);
3727         }
3728         else
3729         {
3730                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3731                 if (developer_loading.integer)
3732                 {
3733                         Con_Printf("(tried tried images ");
3734                         for (j = 0;j < 3;j++)
3735                                 for (i = 0;i < 6;i++)
3736                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3737                         Con_Print(" and was unable to find any of them).\n");
3738                 }
3739         }
3740         return cubemaptexture;
3741 }
3742
3743 rtexture_t *R_GetCubemap(const char *basename)
3744 {
3745         int i;
3746         for (i = 0;i < r_texture_numcubemaps;i++)
3747                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3748                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3749         if (i >= MAX_CUBEMAPS)
3750                 return r_texture_whitecube;
3751         r_texture_numcubemaps++;
3752         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3753         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3754         return r_texture_cubemaps[i].texture;
3755 }
3756
3757 void R_FreeCubemaps(void)
3758 {
3759         int i;
3760         for (i = 0;i < r_texture_numcubemaps;i++)
3761         {
3762                 if (developer_loading.integer)
3763                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3764                 if (r_texture_cubemaps[i].texture)
3765                         R_FreeTexture(r_texture_cubemaps[i].texture);
3766         }
3767         r_texture_numcubemaps = 0;
3768 }
3769
3770 void R_Main_FreeViewCache(void)
3771 {
3772         if (r_refdef.viewcache.entityvisible)
3773                 Mem_Free(r_refdef.viewcache.entityvisible);
3774         if (r_refdef.viewcache.world_pvsbits)
3775                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3776         if (r_refdef.viewcache.world_leafvisible)
3777                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3778         if (r_refdef.viewcache.world_surfacevisible)
3779                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3780         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3781 }
3782
3783 void R_Main_ResizeViewCache(void)
3784 {
3785         int numentities = r_refdef.scene.numentities;
3786         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3787         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3788         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3789         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3790         if (r_refdef.viewcache.maxentities < numentities)
3791         {
3792                 r_refdef.viewcache.maxentities = numentities;
3793                 if (r_refdef.viewcache.entityvisible)
3794                         Mem_Free(r_refdef.viewcache.entityvisible);
3795                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3796         }
3797         if (r_refdef.viewcache.world_numclusters != numclusters)
3798         {
3799                 r_refdef.viewcache.world_numclusters = numclusters;
3800                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3801                 if (r_refdef.viewcache.world_pvsbits)
3802                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3803                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3804         }
3805         if (r_refdef.viewcache.world_numleafs != numleafs)
3806         {
3807                 r_refdef.viewcache.world_numleafs = numleafs;
3808                 if (r_refdef.viewcache.world_leafvisible)
3809                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3810                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3811         }
3812         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3813         {
3814                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3815                 if (r_refdef.viewcache.world_surfacevisible)
3816                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3817                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3818         }
3819 }
3820
3821 extern rtexture_t *loadingscreentexture;
3822 void gl_main_start(void)
3823 {
3824         loadingscreentexture = NULL;
3825         r_texture_blanknormalmap = NULL;
3826         r_texture_white = NULL;
3827         r_texture_grey128 = NULL;
3828         r_texture_black = NULL;
3829         r_texture_whitecube = NULL;
3830         r_texture_normalizationcube = NULL;
3831         r_texture_fogattenuation = NULL;
3832         r_texture_fogheighttexture = NULL;
3833         r_texture_gammaramps = NULL;
3834         r_texture_numcubemaps = 0;
3835
3836         r_loaddds = r_texture_dds_load.integer != 0;
3837         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3838
3839         switch(vid.renderpath)
3840         {
3841         case RENDERPATH_GL20:
3842         case RENDERPATH_D3D9:
3843         case RENDERPATH_D3D10:
3844         case RENDERPATH_D3D11:
3845         case RENDERPATH_SOFT:
3846         case RENDERPATH_GLES2:
3847                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3848                 Cvar_SetValueQuick(&gl_combine, 1);
3849                 Cvar_SetValueQuick(&r_glsl, 1);
3850                 r_loadnormalmap = true;
3851                 r_loadgloss = true;
3852                 r_loadfog = false;
3853                 break;
3854         case RENDERPATH_GL13:
3855         case RENDERPATH_GLES1:
3856                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3857                 Cvar_SetValueQuick(&gl_combine, 1);
3858                 Cvar_SetValueQuick(&r_glsl, 0);
3859                 r_loadnormalmap = false;
3860                 r_loadgloss = false;
3861                 r_loadfog = true;
3862                 break;
3863         case RENDERPATH_GL11:
3864                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3865                 Cvar_SetValueQuick(&gl_combine, 0);
3866                 Cvar_SetValueQuick(&r_glsl, 0);
3867                 r_loadnormalmap = false;
3868                 r_loadgloss = false;
3869                 r_loadfog = true;
3870                 break;
3871         }
3872
3873         R_AnimCache_Free();
3874         R_FrameData_Reset();
3875
3876         r_numqueries = 0;
3877         r_maxqueries = 0;
3878         memset(r_queries, 0, sizeof(r_queries));
3879
3880         r_qwskincache = NULL;
3881         r_qwskincache_size = 0;
3882
3883         // due to caching of texture_t references, the collision cache must be reset
3884         Collision_Cache_Reset(true);
3885
3886         // set up r_skinframe loading system for textures
3887         memset(&r_skinframe, 0, sizeof(r_skinframe));
3888         r_skinframe.loadsequence = 1;
3889         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3890
3891         r_main_texturepool = R_AllocTexturePool();
3892         R_BuildBlankTextures();
3893         R_BuildNoTexture();
3894         if (vid.support.arb_texture_cube_map)
3895         {
3896                 R_BuildWhiteCube();
3897                 R_BuildNormalizationCube();
3898         }
3899         r_texture_fogattenuation = NULL;
3900         r_texture_fogheighttexture = NULL;
3901         r_texture_gammaramps = NULL;
3902         //r_texture_fogintensity = NULL;
3903         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3904         memset(&r_waterstate, 0, sizeof(r_waterstate));
3905         r_glsl_permutation = NULL;
3906         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3907         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3908         glslshaderstring = NULL;
3909 #ifdef SUPPORTD3D
3910         r_hlsl_permutation = NULL;
3911         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3912         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3913 #endif
3914         hlslshaderstring = NULL;
3915         memset(&r_svbsp, 0, sizeof (r_svbsp));
3916
3917         r_refdef.fogmasktable_density = 0;
3918 }
3919
3920 void gl_main_shutdown(void)
3921 {
3922         R_AnimCache_Free();
3923         R_FrameData_Reset();
3924
3925         R_Main_FreeViewCache();
3926
3927         switch(vid.renderpath)
3928         {
3929         case RENDERPATH_GL11:
3930         case RENDERPATH_GL13:
3931         case RENDERPATH_GL20:
3932         case RENDERPATH_GLES1:
3933         case RENDERPATH_GLES2:
3934                 if (r_maxqueries)
3935                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3936                 break;
3937         case RENDERPATH_D3D9:
3938                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3939                 break;
3940         case RENDERPATH_D3D10:
3941                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3942                 break;
3943         case RENDERPATH_D3D11:
3944                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3945                 break;
3946         case RENDERPATH_SOFT:
3947                 break;
3948         }
3949
3950         r_numqueries = 0;
3951         r_maxqueries = 0;
3952         memset(r_queries, 0, sizeof(r_queries));
3953
3954         r_qwskincache = NULL;
3955         r_qwskincache_size = 0;
3956
3957         // clear out the r_skinframe state
3958         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3959         memset(&r_skinframe, 0, sizeof(r_skinframe));
3960
3961         if (r_svbsp.nodes)
3962                 Mem_Free(r_svbsp.nodes);
3963         memset(&r_svbsp, 0, sizeof (r_svbsp));
3964         R_FreeTexturePool(&r_main_texturepool);
3965         loadingscreentexture = NULL;
3966         r_texture_blanknormalmap = NULL;
3967         r_texture_white = NULL;
3968         r_texture_grey128 = NULL;
3969         r_texture_black = NULL;
3970         r_texture_whitecube = NULL;
3971         r_texture_normalizationcube = NULL;
3972         r_texture_fogattenuation = NULL;
3973         r_texture_fogheighttexture = NULL;
3974         r_texture_gammaramps = NULL;
3975         r_texture_numcubemaps = 0;
3976         //r_texture_fogintensity = NULL;
3977         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3978         memset(&r_waterstate, 0, sizeof(r_waterstate));
3979         R_GLSL_Restart_f();
3980
3981         r_glsl_permutation = NULL;
3982         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3983         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3984         glslshaderstring = NULL;
3985 #ifdef SUPPORTD3D
3986         r_hlsl_permutation = NULL;
3987         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3988         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3989 #endif
3990         hlslshaderstring = NULL;
3991 }
3992
3993 extern void CL_ParseEntityLump(char *entitystring);
3994 void gl_main_newmap(void)
3995 {
3996         // FIXME: move this code to client
3997         char *entities, entname[MAX_QPATH];
3998         if (r_qwskincache)
3999                 Mem_Free(r_qwskincache);
4000         r_qwskincache = NULL;
4001         r_qwskincache_size = 0;
4002         if (cl.worldmodel)
4003         {
4004                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4005                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4006                 {
4007                         CL_ParseEntityLump(entities);
4008                         Mem_Free(entities);
4009                         return;
4010                 }
4011                 if (cl.worldmodel->brush.entities)
4012                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4013         }
4014         R_Main_FreeViewCache();
4015
4016         R_FrameData_Reset();
4017 }
4018
4019 void GL_Main_Init(void)
4020 {
4021         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4022
4023         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4024         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4025         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4026         if (gamemode == GAME_NEHAHRA)
4027         {
4028                 Cvar_RegisterVariable (&gl_fogenable);
4029                 Cvar_RegisterVariable (&gl_fogdensity);
4030                 Cvar_RegisterVariable (&gl_fogred);
4031                 Cvar_RegisterVariable (&gl_foggreen);
4032                 Cvar_RegisterVariable (&gl_fogblue);
4033                 Cvar_RegisterVariable (&gl_fogstart);
4034                 Cvar_RegisterVariable (&gl_fogend);
4035                 Cvar_RegisterVariable (&gl_skyclip);
4036         }
4037         Cvar_RegisterVariable(&r_motionblur);
4038         Cvar_RegisterVariable(&r_motionblur_maxblur);
4039         Cvar_RegisterVariable(&r_motionblur_bmin);
4040         Cvar_RegisterVariable(&r_motionblur_vmin);
4041         Cvar_RegisterVariable(&r_motionblur_vmax);
4042         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4043         Cvar_RegisterVariable(&r_motionblur_randomize);
4044         Cvar_RegisterVariable(&r_damageblur);
4045         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4046         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4047         Cvar_RegisterVariable(&r_equalize_entities_by);
4048         Cvar_RegisterVariable(&r_equalize_entities_to);
4049         Cvar_RegisterVariable(&r_depthfirst);
4050         Cvar_RegisterVariable(&r_useinfinitefarclip);
4051         Cvar_RegisterVariable(&r_farclip_base);
4052         Cvar_RegisterVariable(&r_farclip_world);
4053         Cvar_RegisterVariable(&r_nearclip);
4054         Cvar_RegisterVariable(&r_showoverdraw);
4055         Cvar_RegisterVariable(&r_showbboxes);
4056         Cvar_RegisterVariable(&r_showsurfaces);
4057         Cvar_RegisterVariable(&r_showtris);
4058         Cvar_RegisterVariable(&r_shownormals);
4059         Cvar_RegisterVariable(&r_showlighting);
4060         Cvar_RegisterVariable(&r_showshadowvolumes);
4061         Cvar_RegisterVariable(&r_showcollisionbrushes);
4062         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4063         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4064         Cvar_RegisterVariable(&r_showdisabledepthtest);
4065         Cvar_RegisterVariable(&r_drawportals);
4066         Cvar_RegisterVariable(&r_drawentities);
4067         Cvar_RegisterVariable(&r_draw2d);
4068         Cvar_RegisterVariable(&r_drawworld);
4069         Cvar_RegisterVariable(&r_cullentities_trace);
4070         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4071         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4072         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4073         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4074         Cvar_RegisterVariable(&r_drawviewmodel);
4075         Cvar_RegisterVariable(&r_drawexteriormodel);
4076         Cvar_RegisterVariable(&r_speeds);
4077         Cvar_RegisterVariable(&r_fullbrights);
4078         Cvar_RegisterVariable(&r_wateralpha);
4079         Cvar_RegisterVariable(&r_dynamic);
4080         Cvar_RegisterVariable(&r_fakelight);
4081         Cvar_RegisterVariable(&r_fakelight_intensity);
4082         Cvar_RegisterVariable(&r_fullbright);
4083         Cvar_RegisterVariable(&r_shadows);
4084         Cvar_RegisterVariable(&r_shadows_darken);
4085         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4086         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4087         Cvar_RegisterVariable(&r_shadows_throwdistance);
4088         Cvar_RegisterVariable(&r_shadows_throwdirection);
4089         Cvar_RegisterVariable(&r_shadows_focus);
4090         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4091         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4092         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4093         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4094         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4095         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4096         Cvar_RegisterVariable(&r_fog_exp2);
4097         Cvar_RegisterVariable(&r_fog_clear);
4098         Cvar_RegisterVariable(&r_drawfog);
4099         Cvar_RegisterVariable(&r_transparentdepthmasking);
4100         Cvar_RegisterVariable(&r_texture_dds_load);
4101         Cvar_RegisterVariable(&r_texture_dds_save);
4102         Cvar_RegisterVariable(&r_texture_sRGB_2d);
4103         Cvar_RegisterVariable(&r_texture_sRGB_skin_diffuse);
4104         Cvar_RegisterVariable(&r_texture_sRGB_skin_gloss);
4105         Cvar_RegisterVariable(&r_texture_sRGB_skin_glow);
4106         Cvar_RegisterVariable(&r_texture_sRGB_skin_reflect);
4107         Cvar_RegisterVariable(&r_texture_sRGB_cubemap);
4108         Cvar_RegisterVariable(&r_texture_sRGB_skybox);
4109         Cvar_RegisterVariable(&r_textureunits);
4110         Cvar_RegisterVariable(&gl_combine);
4111         Cvar_RegisterVariable(&r_viewfbo);
4112         Cvar_RegisterVariable(&r_viewscale);
4113         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4114         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4115         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4116         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4117         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4118         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4119         Cvar_RegisterVariable(&r_glsl);
4120         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4121         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4122         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4123         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4124         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4125         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4126         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4127         Cvar_RegisterVariable(&r_glsl_postprocess);
4128         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4129         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4130         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4131         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4132         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4133         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4134         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4135         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4136
4137         Cvar_RegisterVariable(&r_water);
4138         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4139         Cvar_RegisterVariable(&r_water_clippingplanebias);
4140         Cvar_RegisterVariable(&r_water_refractdistort);
4141         Cvar_RegisterVariable(&r_water_reflectdistort);
4142         Cvar_RegisterVariable(&r_water_scissormode);
4143         Cvar_RegisterVariable(&r_lerpsprites);
4144         Cvar_RegisterVariable(&r_lerpmodels);
4145         Cvar_RegisterVariable(&r_lerplightstyles);
4146         Cvar_RegisterVariable(&r_waterscroll);
4147         Cvar_RegisterVariable(&r_bloom);
4148         Cvar_RegisterVariable(&r_bloom_colorscale);
4149         Cvar_RegisterVariable(&r_bloom_brighten);
4150         Cvar_RegisterVariable(&r_bloom_blur);
4151         Cvar_RegisterVariable(&r_bloom_resolution);
4152         Cvar_RegisterVariable(&r_bloom_colorexponent);
4153         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4154         Cvar_RegisterVariable(&r_hdr);
4155         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4156         Cvar_RegisterVariable(&r_hdr_glowintensity);
4157         Cvar_RegisterVariable(&r_hdr_range);
4158         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4159         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4160         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4161         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4162         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4163         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4164         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4165         Cvar_RegisterVariable(&developer_texturelogging);
4166         Cvar_RegisterVariable(&gl_lightmaps);
4167         Cvar_RegisterVariable(&r_test);
4168         Cvar_RegisterVariable(&r_glsl_saturation);
4169         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4170         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4171         Cvar_RegisterVariable(&r_framedatasize);
4172         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4173                 Cvar_SetValue("r_fullbrights", 0);
4174         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4175
4176         Cvar_RegisterVariable(&r_track_sprites);
4177         Cvar_RegisterVariable(&r_track_sprites_flags);
4178         Cvar_RegisterVariable(&r_track_sprites_scalew);
4179         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4180         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4181         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4182         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4183         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4184 }
4185
4186 extern void R_Textures_Init(void);
4187 extern void GL_Draw_Init(void);
4188 extern void GL_Main_Init(void);
4189 extern void R_Shadow_Init(void);
4190 extern void R_Sky_Init(void);
4191 extern void GL_Surf_Init(void);
4192 extern void R_Particles_Init(void);
4193 extern void R_Explosion_Init(void);
4194 extern void gl_backend_init(void);
4195 extern void Sbar_Init(void);
4196 extern void R_LightningBeams_Init(void);
4197 extern void Mod_RenderInit(void);
4198 extern void Font_Init(void);
4199
4200 void Render_Init(void)
4201 {
4202         gl_backend_init();
4203         R_Textures_Init();
4204         GL_Main_Init();
4205         Font_Init();
4206         GL_Draw_Init();
4207         R_Shadow_Init();
4208         R_Sky_Init();
4209         GL_Surf_Init();
4210         Sbar_Init();
4211         R_Particles_Init();
4212         R_Explosion_Init();
4213         R_LightningBeams_Init();
4214         Mod_RenderInit();
4215 }
4216
4217 /*
4218 ===============
4219 GL_Init
4220 ===============
4221 */
4222 extern char *ENGINE_EXTENSIONS;
4223 void GL_Init (void)
4224 {
4225         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4226         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4227         gl_version = (const char *)qglGetString(GL_VERSION);
4228         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4229
4230         if (!gl_extensions)
4231                 gl_extensions = "";
4232         if (!gl_platformextensions)
4233                 gl_platformextensions = "";
4234
4235         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4236         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4237         Con_Printf("GL_VERSION: %s\n", gl_version);
4238         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4239         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4240
4241         VID_CheckExtensions();
4242
4243         // LordHavoc: report supported extensions
4244         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4245
4246         // clear to black (loading plaque will be seen over this)
4247         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4248 }
4249
4250 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4251 {
4252         int i;
4253         mplane_t *p;
4254         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4255         {
4256                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4257                 if (i == 4)
4258                         continue;
4259                 p = r_refdef.view.frustum + i;
4260                 switch(p->signbits)
4261                 {
4262                 default:
4263                 case 0:
4264                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4265                                 return true;
4266                         break;
4267                 case 1:
4268                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4269                                 return true;
4270                         break;
4271                 case 2:
4272                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4273                                 return true;
4274                         break;
4275                 case 3:
4276                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4277                                 return true;
4278                         break;
4279                 case 4:
4280                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4281                                 return true;
4282                         break;
4283                 case 5:
4284                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4285                                 return true;
4286                         break;
4287                 case 6:
4288                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4289                                 return true;
4290                         break;
4291                 case 7:
4292                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4293                                 return true;
4294                         break;
4295                 }
4296         }
4297         return false;
4298 }
4299
4300 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4301 {
4302         int i;
4303         const mplane_t *p;
4304         for (i = 0;i < numplanes;i++)
4305         {
4306                 p = planes + i;
4307                 switch(p->signbits)
4308                 {
4309                 default:
4310                 case 0:
4311                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4312                                 return true;
4313                         break;
4314                 case 1:
4315                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4316                                 return true;
4317                         break;
4318                 case 2:
4319                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4320                                 return true;
4321                         break;
4322                 case 3:
4323                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4324                                 return true;
4325                         break;
4326                 case 4:
4327                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4328                                 return true;
4329                         break;
4330                 case 5:
4331                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4332                                 return true;
4333                         break;
4334                 case 6:
4335                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4336                                 return true;
4337                         break;
4338                 case 7:
4339                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4340                                 return true;
4341                         break;
4342                 }
4343         }
4344         return false;
4345 }
4346
4347 //==================================================================================
4348
4349 // LordHavoc: this stores temporary data used within the same frame
4350
4351 typedef struct r_framedata_mem_s
4352 {
4353         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4354         size_t size; // how much usable space
4355         size_t current; // how much space in use
4356         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4357         size_t wantedsize; // how much space was allocated
4358         unsigned char *data; // start of real data (16byte aligned)
4359 }
4360 r_framedata_mem_t;
4361
4362 static r_framedata_mem_t *r_framedata_mem;
4363
4364 void R_FrameData_Reset(void)
4365 {
4366         while (r_framedata_mem)
4367         {
4368                 r_framedata_mem_t *next = r_framedata_mem->purge;
4369                 Mem_Free(r_framedata_mem);
4370                 r_framedata_mem = next;
4371         }
4372 }
4373
4374 void R_FrameData_Resize(void)
4375 {
4376         size_t wantedsize;
4377         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4378         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4379         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4380         {
4381                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4382                 newmem->wantedsize = wantedsize;
4383                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4384                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4385                 newmem->current = 0;
4386                 newmem->mark = 0;
4387                 newmem->purge = r_framedata_mem;
4388                 r_framedata_mem = newmem;
4389         }
4390 }
4391
4392 void R_FrameData_NewFrame(void)
4393 {
4394         R_FrameData_Resize();
4395         if (!r_framedata_mem)
4396                 return;
4397         // if we ran out of space on the last frame, free the old memory now
4398         while (r_framedata_mem->purge)
4399         {
4400                 // repeatedly remove the second item in the list, leaving only head
4401                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4402                 Mem_Free(r_framedata_mem->purge);
4403                 r_framedata_mem->purge = next;
4404         }
4405         // reset the current mem pointer
4406         r_framedata_mem->current = 0;
4407         r_framedata_mem->mark = 0;
4408 }
4409
4410 void *R_FrameData_Alloc(size_t size)
4411 {
4412         void *data;
4413
4414         // align to 16 byte boundary - the data pointer is already aligned, so we
4415         // only need to ensure the size of every allocation is also aligned
4416         size = (size + 15) & ~15;
4417
4418         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4419         {
4420                 // emergency - we ran out of space, allocate more memory
4421                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4422                 R_FrameData_Resize();
4423         }
4424
4425         data = r_framedata_mem->data + r_framedata_mem->current;
4426         r_framedata_mem->current += size;
4427
4428         // count the usage for stats
4429         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4430         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4431
4432         return (void *)data;
4433 }
4434
4435 void *R_FrameData_Store(size_t size, void *data)
4436 {
4437         void *d = R_FrameData_Alloc(size);
4438         if (d && data)
4439                 memcpy(d, data, size);
4440         return d;
4441 }
4442
4443 void R_FrameData_SetMark(void)
4444 {
4445         if (!r_framedata_mem)
4446                 return;
4447         r_framedata_mem->mark = r_framedata_mem->current;
4448 }
4449
4450 void R_FrameData_ReturnToMark(void)
4451 {
4452         if (!r_framedata_mem)
4453                 return;
4454         r_framedata_mem->current = r_framedata_mem->mark;
4455 }
4456
4457 //==================================================================================
4458
4459 // LordHavoc: animcache originally written by Echon, rewritten since then
4460
4461 /**
4462  * Animation cache prevents re-generating mesh data for an animated model
4463  * multiple times in one frame for lighting, shadowing, reflections, etc.
4464  */
4465
4466 void R_AnimCache_Free(void)
4467 {
4468 }
4469
4470 void R_AnimCache_ClearCache(void)
4471 {
4472         int i;
4473         entity_render_t *ent;
4474
4475         for (i = 0;i < r_refdef.scene.numentities;i++)
4476         {
4477                 ent = r_refdef.scene.entities[i];
4478                 ent->animcache_vertex3f = NULL;
4479                 ent->animcache_normal3f = NULL;
4480                 ent->animcache_svector3f = NULL;
4481                 ent->animcache_tvector3f = NULL;
4482                 ent->animcache_vertexmesh = NULL;
4483                 ent->animcache_vertex3fbuffer = NULL;
4484                 ent->animcache_vertexmeshbuffer = NULL;
4485         }
4486 }
4487
4488 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4489 {
4490         int i;
4491
4492         // check if we need the meshbuffers
4493         if (!vid.useinterleavedarrays)
4494                 return;
4495
4496         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4497                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4498         // TODO: upload vertex3f buffer?
4499         if (ent->animcache_vertexmesh)
4500         {
4501                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4502                 for (i = 0;i < numvertices;i++)
4503                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4504                 if (ent->animcache_svector3f)
4505                         for (i = 0;i < numvertices;i++)
4506                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4507                 if (ent->animcache_tvector3f)
4508                         for (i = 0;i < numvertices;i++)
4509                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4510                 if (ent->animcache_normal3f)
4511                         for (i = 0;i < numvertices;i++)
4512                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4513                 // TODO: upload vertexmeshbuffer?
4514         }
4515 }
4516
4517 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4518 {
4519         dp_model_t *model = ent->model;
4520         int numvertices;
4521         // see if it's already cached this frame
4522         if (ent->animcache_vertex3f)
4523         {
4524                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4525                 if (wantnormals || wanttangents)
4526                 {
4527                         if (ent->animcache_normal3f)
4528                                 wantnormals = false;
4529                         if (ent->animcache_svector3f)
4530                                 wanttangents = false;
4531                         if (wantnormals || wanttangents)
4532                         {
4533                                 numvertices = model->surfmesh.num_vertices;
4534                                 if (wantnormals)
4535                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4536                                 if (wanttangents)
4537                                 {
4538                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4539                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4540                                 }
4541                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4542                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4543                         }
4544                 }
4545         }
4546         else
4547         {
4548                 // see if this ent is worth caching
4549                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4550                         return false;
4551                 // get some memory for this entity and generate mesh data
4552                 numvertices = model->surfmesh.num_vertices;
4553                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4554                 if (wantnormals)
4555                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4556                 if (wanttangents)
4557                 {
4558                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4559                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4560                 }
4561                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4562                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4563         }
4564         return true;
4565 }
4566
4567 void R_AnimCache_CacheVisibleEntities(void)
4568 {
4569         int i;
4570         qboolean wantnormals = true;
4571         qboolean wanttangents = !r_showsurfaces.integer;
4572
4573         switch(vid.renderpath)
4574         {
4575         case RENDERPATH_GL20:
4576         case RENDERPATH_D3D9:
4577         case RENDERPATH_D3D10:
4578         case RENDERPATH_D3D11:
4579         case RENDERPATH_GLES2:
4580                 break;
4581         case RENDERPATH_GL11:
4582         case RENDERPATH_GL13:
4583         case RENDERPATH_GLES1:
4584                 wanttangents = false;
4585                 break;
4586         case RENDERPATH_SOFT:
4587                 break;
4588         }
4589
4590         if (r_shownormals.integer)
4591                 wanttangents = wantnormals = true;
4592
4593         // TODO: thread this
4594         // NOTE: R_PrepareRTLights() also caches entities
4595
4596         for (i = 0;i < r_refdef.scene.numentities;i++)
4597                 if (r_refdef.viewcache.entityvisible[i])
4598                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4599 }
4600
4601 //==================================================================================
4602
4603 static void R_View_UpdateEntityLighting (void)
4604 {
4605         int i;
4606         entity_render_t *ent;
4607         vec3_t tempdiffusenormal, avg;
4608         vec_t f, fa, fd, fdd;
4609         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4610
4611         for (i = 0;i < r_refdef.scene.numentities;i++)
4612         {
4613                 ent = r_refdef.scene.entities[i];
4614
4615                 // skip unseen models
4616                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4617                         continue;
4618
4619                 // skip bsp models
4620                 if (ent->model && ent->model->brush.num_leafs)
4621                 {
4622                         // TODO: use modellight for r_ambient settings on world?
4623                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4624                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4625                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4626                         continue;
4627                 }
4628
4629                 // fetch the lighting from the worldmodel data
4630                 VectorClear(ent->modellight_ambient);
4631                 VectorClear(ent->modellight_diffuse);
4632                 VectorClear(tempdiffusenormal);
4633                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4634                 {
4635                         vec3_t org;
4636                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4637
4638                         // complete lightning for lit sprites
4639                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4640                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4641                         {
4642                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4643                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4644                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4645                         }
4646                         else
4647                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4648
4649                         if(ent->flags & RENDER_EQUALIZE)
4650                         {
4651                                 // first fix up ambient lighting...
4652                                 if(r_equalize_entities_minambient.value > 0)
4653                                 {
4654                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4655                                         if(fd > 0)
4656                                         {
4657                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4658                                                 if(fa < r_equalize_entities_minambient.value * fd)
4659                                                 {
4660                                                         // solve:
4661                                                         //   fa'/fd' = minambient
4662                                                         //   fa'+0.25*fd' = fa+0.25*fd
4663                                                         //   ...
4664                                                         //   fa' = fd' * minambient
4665                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4666                                                         //   ...
4667                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4668                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4669                                                         //   ...
4670                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4671                                                         f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
4672                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4673                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4674                                                 }
4675                                         }
4676                                 }
4677
4678                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4679                                 {
4680                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4681                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4682                                         f = fa + 0.25 * fd;
4683                                         if(f > 0)
4684                                         {
4685                                                 // adjust brightness and saturation to target
4686                                                 avg[0] = avg[1] = avg[2] = fa / f;
4687                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4688                                                 avg[0] = avg[1] = avg[2] = fd / f;
4689                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4690                                         }
4691                                 }
4692                         }
4693                 }
4694                 else // highly rare
4695                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4696
4697                 // move the light direction into modelspace coordinates for lighting code
4698                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4699                 if(VectorLength2(ent->modellight_lightdir) == 0)
4700                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4701                 VectorNormalize(ent->modellight_lightdir);
4702         }
4703 }
4704
4705 #define MAX_LINEOFSIGHTTRACES 64
4706
4707 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4708 {
4709         int i;
4710         vec3_t boxmins, boxmaxs;
4711         vec3_t start;
4712         vec3_t end;
4713         dp_model_t *model = r_refdef.scene.worldmodel;
4714
4715         if (!model || !model->brush.TraceLineOfSight)
4716                 return true;
4717
4718         // expand the box a little
4719         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4720         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4721         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4722         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4723         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4724         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4725
4726         // return true if eye is inside enlarged box
4727         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4728                 return true;
4729
4730         // try center
4731         VectorCopy(eye, start);
4732         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4733         if (model->brush.TraceLineOfSight(model, start, end))
4734                 return true;
4735
4736         // try various random positions
4737         for (i = 0;i < numsamples;i++)
4738         {
4739                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4740                 if (model->brush.TraceLineOfSight(model, start, end))
4741                         return true;
4742         }
4743
4744         return false;
4745 }
4746
4747
4748 static void R_View_UpdateEntityVisible (void)
4749 {
4750         int i;
4751         int renderimask;
4752         int samples;
4753         entity_render_t *ent;
4754
4755         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4756                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4757                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4758                 :                                                          RENDER_EXTERIORMODEL;
4759         if (!r_drawviewmodel.integer)
4760                 renderimask |= RENDER_VIEWMODEL;
4761         if (!r_drawexteriormodel.integer)
4762                 renderimask |= RENDER_EXTERIORMODEL;
4763         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4764         {
4765                 // worldmodel can check visibility
4766                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4767                 for (i = 0;i < r_refdef.scene.numentities;i++)
4768                 {
4769                         ent = r_refdef.scene.entities[i];
4770                         if (!(ent->flags & renderimask))
4771                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
4772                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4773                                 r_refdef.viewcache.entityvisible[i] = true;
4774                 }
4775         }
4776         else
4777         {
4778                 // no worldmodel or it can't check visibility
4779                 for (i = 0;i < r_refdef.scene.numentities;i++)
4780                 {
4781                         ent = r_refdef.scene.entities[i];
4782                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
4783                 }
4784         }
4785         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4786                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4787         {
4788                 for (i = 0;i < r_refdef.scene.numentities;i++)
4789                 {
4790                         if (!r_refdef.viewcache.entityvisible[i])
4791                                 continue;
4792                         ent = r_refdef.scene.entities[i];
4793                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4794                         {
4795                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4796                                 if (samples < 0)
4797                                         continue; // temp entities do pvs only
4798                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4799                                         ent->last_trace_visibility = realtime;
4800                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4801                                         r_refdef.viewcache.entityvisible[i] = 0;
4802                         }
4803                 }
4804         }
4805 }
4806
4807 /// only used if skyrendermasked, and normally returns false
4808 int R_DrawBrushModelsSky (void)
4809 {
4810         int i, sky;
4811         entity_render_t *ent;
4812
4813         sky = false;
4814         for (i = 0;i < r_refdef.scene.numentities;i++)
4815         {
4816                 if (!r_refdef.viewcache.entityvisible[i])
4817                         continue;
4818                 ent = r_refdef.scene.entities[i];
4819                 if (!ent->model || !ent->model->DrawSky)
4820                         continue;
4821                 ent->model->DrawSky(ent);
4822                 sky = true;
4823         }
4824         return sky;
4825 }
4826
4827 static void R_DrawNoModel(entity_render_t *ent);
4828 static void R_DrawModels(void)
4829 {
4830         int i;
4831         entity_render_t *ent;
4832
4833         for (i = 0;i < r_refdef.scene.numentities;i++)
4834         {
4835                 if (!r_refdef.viewcache.entityvisible[i])
4836                         continue;
4837                 ent = r_refdef.scene.entities[i];
4838                 r_refdef.stats.entities++;
4839                 if (ent->model && ent->model->Draw != NULL)
4840                         ent->model->Draw(ent);
4841                 else
4842                         R_DrawNoModel(ent);
4843         }
4844 }
4845
4846 static void R_DrawModelsDepth(void)
4847 {
4848         int i;
4849         entity_render_t *ent;
4850
4851         for (i = 0;i < r_refdef.scene.numentities;i++)
4852         {
4853                 if (!r_refdef.viewcache.entityvisible[i])
4854                         continue;
4855                 ent = r_refdef.scene.entities[i];
4856                 if (ent->model && ent->model->DrawDepth != NULL)
4857                         ent->model->DrawDepth(ent);
4858         }
4859 }
4860
4861 static void R_DrawModelsDebug(void)
4862 {
4863         int i;
4864         entity_render_t *ent;
4865
4866         for (i = 0;i < r_refdef.scene.numentities;i++)
4867         {
4868                 if (!r_refdef.viewcache.entityvisible[i])
4869                         continue;
4870                 ent = r_refdef.scene.entities[i];
4871                 if (ent->model && ent->model->DrawDebug != NULL)
4872                         ent->model->DrawDebug(ent);
4873         }
4874 }
4875
4876 static void R_DrawModelsAddWaterPlanes(void)
4877 {
4878         int i;
4879         entity_render_t *ent;
4880
4881         for (i = 0;i < r_refdef.scene.numentities;i++)
4882         {
4883                 if (!r_refdef.viewcache.entityvisible[i])
4884                         continue;
4885                 ent = r_refdef.scene.entities[i];
4886                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4887                         ent->model->DrawAddWaterPlanes(ent);
4888         }
4889 }
4890
4891 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4892 {
4893         if (r_hdr_irisadaptation.integer)
4894         {
4895                 vec3_t ambient;
4896                 vec3_t diffuse;
4897                 vec3_t diffusenormal;
4898                 vec_t brightness;
4899                 vec_t goal;
4900                 vec_t adjust;
4901                 vec_t current;
4902                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4903                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4904                 brightness = max(0.0000001f, brightness);
4905                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4906                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4907                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4908                 current = r_hdr_irisadaptation_value.value;
4909                 if (current < goal)
4910                         current = min(current + adjust, goal);
4911                 else if (current > goal)
4912                         current = max(current - adjust, goal);
4913                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4914                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4915         }
4916         else if (r_hdr_irisadaptation_value.value != 1.0f)
4917                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4918 }
4919
4920 static void R_View_SetFrustum(const int *scissor)
4921 {
4922         int i;
4923         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4924         vec3_t forward, left, up, origin, v;
4925
4926         if(scissor)
4927         {
4928                 // flipped x coordinates (because x points left here)
4929                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4930                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4931
4932                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4933                 switch(vid.renderpath)
4934                 {
4935                         case RENDERPATH_D3D9:
4936                         case RENDERPATH_D3D10:
4937                         case RENDERPATH_D3D11:
4938                                 // non-flipped y coordinates
4939                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4940                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4941                                 break;
4942                         case RENDERPATH_SOFT:
4943                         case RENDERPATH_GL11:
4944                         case RENDERPATH_GL13:
4945                         case RENDERPATH_GL20:
4946                         case RENDERPATH_GLES1:
4947                         case RENDERPATH_GLES2:
4948                                 // non-flipped y coordinates
4949                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4950                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4951                                 break;
4952                 }
4953         }
4954
4955         // we can't trust r_refdef.view.forward and friends in reflected scenes
4956         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4957
4958 #if 0
4959         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4960         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4961         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4962         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4963         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4964         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4965         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4966         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4967         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4968         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4969         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4970         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4971 #endif
4972
4973 #if 0
4974         zNear = r_refdef.nearclip;
4975         nudge = 1.0 - 1.0 / (1<<23);
4976         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4977         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4978         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4979         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4980         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4981         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4982         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4983         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4984 #endif
4985
4986
4987
4988 #if 0
4989         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4990         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4991         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4992         r_refdef.view.frustum[0].dist = m[15] - m[12];
4993
4994         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4995         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4996         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4997         r_refdef.view.frustum[1].dist = m[15] + m[12];
4998
4999         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5000         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5001         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5002         r_refdef.view.frustum[2].dist = m[15] - m[13];
5003
5004         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5005         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5006         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5007         r_refdef.view.frustum[3].dist = m[15] + m[13];
5008
5009         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5010         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5011         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5012         r_refdef.view.frustum[4].dist = m[15] - m[14];
5013
5014         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5015         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5016         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5017         r_refdef.view.frustum[5].dist = m[15] + m[14];
5018 #endif
5019
5020         if (r_refdef.view.useperspective)
5021         {
5022                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5023                 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]);
5024                 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]);
5025                 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]);
5026                 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]);
5027
5028                 // then the normals from the corners relative to origin
5029                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5030                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5031                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5032                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5033
5034                 // in a NORMAL view, forward cross left == up
5035                 // in a REFLECTED view, forward cross left == down
5036                 // so our cross products above need to be adjusted for a left handed coordinate system
5037                 CrossProduct(forward, left, v);
5038                 if(DotProduct(v, up) < 0)
5039                 {
5040                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5041                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5042                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5043                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5044                 }
5045
5046                 // Leaving those out was a mistake, those were in the old code, and they
5047                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5048                 // I couldn't reproduce it after adding those normalizations. --blub
5049                 VectorNormalize(r_refdef.view.frustum[0].normal);
5050                 VectorNormalize(r_refdef.view.frustum[1].normal);
5051                 VectorNormalize(r_refdef.view.frustum[2].normal);
5052                 VectorNormalize(r_refdef.view.frustum[3].normal);
5053
5054                 // make the corners absolute
5055                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5056                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5057                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5058                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5059
5060                 // one more normal
5061                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5062
5063                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5064                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5065                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5066                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5067                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5068         }
5069         else
5070         {
5071                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5072                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5073                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5074                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5075                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5076                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5077                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5078                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5079                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5080                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5081         }
5082         r_refdef.view.numfrustumplanes = 5;
5083
5084         if (r_refdef.view.useclipplane)
5085         {
5086                 r_refdef.view.numfrustumplanes = 6;
5087                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5088         }
5089
5090         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5091                 PlaneClassify(r_refdef.view.frustum + i);
5092
5093         // LordHavoc: note to all quake engine coders, Quake had a special case
5094         // for 90 degrees which assumed a square view (wrong), so I removed it,
5095         // Quake2 has it disabled as well.
5096
5097         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5098         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5099         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5100         //PlaneClassify(&frustum[0]);
5101
5102         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5103         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5104         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5105         //PlaneClassify(&frustum[1]);
5106
5107         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5108         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5109         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5110         //PlaneClassify(&frustum[2]);
5111
5112         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5113         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5114         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5115         //PlaneClassify(&frustum[3]);
5116
5117         // nearclip plane
5118         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5119         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5120         //PlaneClassify(&frustum[4]);
5121 }
5122
5123 void R_View_UpdateWithScissor(const int *myscissor)
5124 {
5125         R_Main_ResizeViewCache();
5126         R_View_SetFrustum(myscissor);
5127         R_View_WorldVisibility(r_refdef.view.useclipplane);
5128         R_View_UpdateEntityVisible();
5129         R_View_UpdateEntityLighting();
5130 }
5131
5132 void R_View_Update(void)
5133 {
5134         R_Main_ResizeViewCache();
5135         R_View_SetFrustum(NULL);
5136         R_View_WorldVisibility(r_refdef.view.useclipplane);
5137         R_View_UpdateEntityVisible();
5138         R_View_UpdateEntityLighting();
5139 }
5140
5141 float viewscalefpsadjusted = 1.0f;
5142
5143 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5144 {
5145         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5146         scale = bound(0.03125f, scale, 1.0f);
5147         *outwidth = (int)ceil(width * scale);
5148         *outheight = (int)ceil(height * scale);
5149 }
5150
5151 void R_Mesh_SetMainRenderTargets(void)
5152 {
5153         if (r_bloomstate.fbo_framebuffer)
5154                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5155         else
5156                 R_Mesh_ResetRenderTargets();
5157 }
5158
5159 void R_SetupView(qboolean allowwaterclippingplane)
5160 {
5161         const float *customclipplane = NULL;
5162         float plane[4];
5163         int scaledwidth, scaledheight;
5164         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5165         {
5166                 // LordHavoc: couldn't figure out how to make this approach the
5167                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5168                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5169                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5170                         dist = r_refdef.view.clipplane.dist;
5171                 plane[0] = r_refdef.view.clipplane.normal[0];
5172                 plane[1] = r_refdef.view.clipplane.normal[1];
5173                 plane[2] = r_refdef.view.clipplane.normal[2];
5174                 plane[3] = -dist;
5175                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5176         }
5177
5178         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5179         if (!r_refdef.view.useperspective)
5180                 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);
5181         else if (vid.stencil && r_useinfinitefarclip.integer)
5182                 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);
5183         else
5184                 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);
5185         R_Mesh_SetMainRenderTargets();
5186         R_SetViewport(&r_refdef.view.viewport);
5187         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5188         {
5189                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5190                 float screenplane[4];
5191                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5192                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5193                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5194                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5195                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5196         }
5197 }
5198
5199 void R_EntityMatrix(const matrix4x4_t *matrix)
5200 {
5201         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5202         {
5203                 gl_modelmatrixchanged = false;
5204                 gl_modelmatrix = *matrix;
5205                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5206                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5207                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5208                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5209                 CHECKGLERROR
5210                 switch(vid.renderpath)
5211                 {
5212                 case RENDERPATH_D3D9:
5213 #ifdef SUPPORTD3D
5214                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5215                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5216 #endif
5217                         break;
5218                 case RENDERPATH_D3D10:
5219                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5220                         break;
5221                 case RENDERPATH_D3D11:
5222                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5223                         break;
5224                 case RENDERPATH_GL11:
5225                 case RENDERPATH_GL13:
5226                 case RENDERPATH_GLES1:
5227                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5228                         break;
5229                 case RENDERPATH_SOFT:
5230                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5231                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5232                         break;
5233                 case RENDERPATH_GL20:
5234                 case RENDERPATH_GLES2:
5235                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5236                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5237                         break;
5238                 }
5239         }
5240 }
5241
5242 void R_ResetViewRendering2D(void)
5243 {
5244         r_viewport_t viewport;
5245         DrawQ_Finish();
5246
5247         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5248         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);
5249         R_Mesh_ResetRenderTargets();
5250         R_SetViewport(&viewport);
5251         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5252         GL_Color(1, 1, 1, 1);
5253         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5254         GL_BlendFunc(GL_ONE, GL_ZERO);
5255         GL_ScissorTest(false);
5256         GL_DepthMask(false);
5257         GL_DepthRange(0, 1);
5258         GL_DepthTest(false);
5259         GL_DepthFunc(GL_LEQUAL);
5260         R_EntityMatrix(&identitymatrix);
5261         R_Mesh_ResetTextureState();
5262         GL_PolygonOffset(0, 0);
5263         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5264         switch(vid.renderpath)
5265         {
5266         case RENDERPATH_GL11:
5267         case RENDERPATH_GL13:
5268         case RENDERPATH_GL20:
5269         case RENDERPATH_GLES1:
5270         case RENDERPATH_GLES2:
5271                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5272                 break;
5273         case RENDERPATH_D3D9:
5274         case RENDERPATH_D3D10:
5275         case RENDERPATH_D3D11:
5276         case RENDERPATH_SOFT:
5277                 break;
5278         }
5279         GL_CullFace(GL_NONE);
5280 }
5281
5282 void R_ResetViewRendering3D(void)
5283 {
5284         DrawQ_Finish();
5285
5286         R_SetupView(true);
5287         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5288         GL_Color(1, 1, 1, 1);
5289         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5290         GL_BlendFunc(GL_ONE, GL_ZERO);
5291         GL_ScissorTest(true);
5292         GL_DepthMask(true);
5293         GL_DepthRange(0, 1);
5294         GL_DepthTest(true);
5295         GL_DepthFunc(GL_LEQUAL);
5296         R_EntityMatrix(&identitymatrix);
5297         R_Mesh_ResetTextureState();
5298         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5299         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5300         switch(vid.renderpath)
5301         {
5302         case RENDERPATH_GL11:
5303         case RENDERPATH_GL13:
5304         case RENDERPATH_GL20:
5305         case RENDERPATH_GLES1:
5306         case RENDERPATH_GLES2:
5307                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5308                 break;
5309         case RENDERPATH_D3D9:
5310         case RENDERPATH_D3D10:
5311         case RENDERPATH_D3D11:
5312         case RENDERPATH_SOFT:
5313                 break;
5314         }
5315         GL_CullFace(r_refdef.view.cullface_back);
5316 }
5317
5318 /*
5319 ================
5320 R_RenderView_UpdateViewVectors
5321 ================
5322 */
5323 static void R_RenderView_UpdateViewVectors(void)
5324 {
5325         // break apart the view matrix into vectors for various purposes
5326         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5327         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5328         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5329         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5330         // make an inverted copy of the view matrix for tracking sprites
5331         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5332 }
5333
5334 void R_RenderScene(void);
5335 void R_RenderWaterPlanes(void);
5336
5337 static void R_Water_StartFrame(void)
5338 {
5339         int i;
5340         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5341         r_waterstate_waterplane_t *p;
5342
5343         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5344                 return;
5345
5346         switch(vid.renderpath)
5347         {
5348         case RENDERPATH_GL20:
5349         case RENDERPATH_D3D9:
5350         case RENDERPATH_D3D10:
5351         case RENDERPATH_D3D11:
5352         case RENDERPATH_SOFT:
5353         case RENDERPATH_GLES2:
5354                 break;
5355         case RENDERPATH_GL11:
5356         case RENDERPATH_GL13:
5357         case RENDERPATH_GLES1:
5358                 return;
5359         }
5360
5361         // set waterwidth and waterheight to the water resolution that will be
5362         // used (often less than the screen resolution for faster rendering)
5363         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5364         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5365
5366         // calculate desired texture sizes
5367         // can't use water if the card does not support the texture size
5368         if (!r_water.integer || r_showsurfaces.integer)
5369                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5370         else if (vid.support.arb_texture_non_power_of_two)
5371         {
5372                 texturewidth = waterwidth;
5373                 textureheight = waterheight;
5374                 camerawidth = waterwidth;
5375                 cameraheight = waterheight;
5376         }
5377         else
5378         {
5379                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5380                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5381                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5382                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5383         }
5384
5385         // allocate textures as needed
5386         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5387         {
5388                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5389                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5390                 {
5391                         if (p->texture_refraction)
5392                                 R_FreeTexture(p->texture_refraction);
5393                         p->texture_refraction = NULL;
5394                         if (p->texture_reflection)
5395                                 R_FreeTexture(p->texture_reflection);
5396                         p->texture_reflection = NULL;
5397                         if (p->texture_camera)
5398                                 R_FreeTexture(p->texture_camera);
5399                         p->texture_camera = NULL;
5400                 }
5401                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5402                 r_waterstate.texturewidth = texturewidth;
5403                 r_waterstate.textureheight = textureheight;
5404                 r_waterstate.camerawidth = camerawidth;
5405                 r_waterstate.cameraheight = cameraheight;
5406         }
5407
5408         if (r_waterstate.texturewidth)
5409         {
5410                 r_waterstate.enabled = true;
5411
5412                 // when doing a reduced render (HDR) we want to use a smaller area
5413                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5414                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5415
5416                 // set up variables that will be used in shader setup
5417                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5418                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5419                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5420                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5421         }
5422
5423         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5424         r_waterstate.numwaterplanes = 0;
5425 }
5426
5427 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5428 {
5429         int triangleindex, planeindex;
5430         const int *e;
5431         vec3_t vert[3];
5432         vec3_t normal;
5433         vec3_t center;
5434         mplane_t plane;
5435         r_waterstate_waterplane_t *p;
5436         texture_t *t = R_GetCurrentTexture(surface->texture);
5437
5438         // just use the first triangle with a valid normal for any decisions
5439         VectorClear(normal);
5440         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5441         {
5442                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5443                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5444                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5445                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5446                 if (VectorLength2(normal) >= 0.001)
5447                         break;
5448         }
5449
5450         VectorCopy(normal, plane.normal);
5451         VectorNormalize(plane.normal);
5452         plane.dist = DotProduct(vert[0], plane.normal);
5453         PlaneClassify(&plane);
5454         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5455         {
5456                 // skip backfaces (except if nocullface is set)
5457                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5458                         return;
5459                 VectorNegate(plane.normal, plane.normal);
5460                 plane.dist *= -1;
5461                 PlaneClassify(&plane);
5462         }
5463
5464
5465         // find a matching plane if there is one
5466         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5467                 if(p->camera_entity == t->camera_entity)
5468                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5469                                 break;
5470         if (planeindex >= r_waterstate.maxwaterplanes)
5471                 return; // nothing we can do, out of planes
5472
5473         // if this triangle does not fit any known plane rendered this frame, add one
5474         if (planeindex >= r_waterstate.numwaterplanes)
5475         {
5476                 // store the new plane
5477                 r_waterstate.numwaterplanes++;
5478                 p->plane = plane;
5479                 // clear materialflags and pvs
5480                 p->materialflags = 0;
5481                 p->pvsvalid = false;
5482                 p->camera_entity = t->camera_entity;
5483                 VectorCopy(surface->mins, p->mins);
5484                 VectorCopy(surface->maxs, p->maxs);
5485         }
5486         else
5487         {
5488                 // merge mins/maxs
5489                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5490                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5491                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5492                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5493                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5494                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5495         }
5496         // merge this surface's materialflags into the waterplane
5497         p->materialflags |= t->currentmaterialflags;
5498         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5499         {
5500                 // merge this surface's PVS into the waterplane
5501                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5502                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5503                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5504                 {
5505                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5506                         p->pvsvalid = true;
5507                 }
5508         }
5509 }
5510
5511 static void R_Water_ProcessPlanes(void)
5512 {
5513         int myscissor[4];
5514         r_refdef_view_t originalview;
5515         r_refdef_view_t myview;
5516         int planeindex;
5517         r_waterstate_waterplane_t *p;
5518         vec3_t visorigin;
5519
5520         originalview = r_refdef.view;
5521
5522         // make sure enough textures are allocated
5523         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5524         {
5525                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5526                 {
5527                         if (!p->texture_refraction)
5528                                 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);
5529                         if (!p->texture_refraction)
5530                                 goto error;
5531                 }
5532                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5533                 {
5534                         if (!p->texture_camera)
5535                                 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);
5536                         if (!p->texture_camera)
5537                                 goto error;
5538                 }
5539
5540                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5541                 {
5542                         if (!p->texture_reflection)
5543                                 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);
5544                         if (!p->texture_reflection)
5545                                 goto error;
5546                 }
5547         }
5548
5549         // render views
5550         r_refdef.view = originalview;
5551         r_refdef.view.showdebug = false;
5552         r_refdef.view.width = r_waterstate.waterwidth;
5553         r_refdef.view.height = r_waterstate.waterheight;
5554         r_refdef.view.useclipplane = true;
5555         myview = r_refdef.view;
5556         r_waterstate.renderingscene = true;
5557         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5558         {
5559                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5560                 {
5561                         r_refdef.view = myview;
5562                         if(r_water_scissormode.integer)
5563                         {
5564                                 R_SetupView(true);
5565                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5566                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5567                         }
5568
5569                         // render reflected scene and copy into texture
5570                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5571                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5572                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5573                         r_refdef.view.clipplane = p->plane;
5574
5575                         // reverse the cullface settings for this render
5576                         r_refdef.view.cullface_front = GL_FRONT;
5577                         r_refdef.view.cullface_back = GL_BACK;
5578                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5579                         {
5580                                 r_refdef.view.usecustompvs = true;
5581                                 if (p->pvsvalid)
5582                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5583                                 else
5584                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5585                         }
5586
5587                         R_ResetViewRendering3D();
5588                         R_ClearScreen(r_refdef.fogenabled);
5589                         if(r_water_scissormode.integer & 2)
5590                                 R_View_UpdateWithScissor(myscissor);
5591                         else
5592                                 R_View_Update();
5593                         if(r_water_scissormode.integer & 1)
5594                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5595                         R_RenderScene();
5596
5597                         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);
5598                 }
5599
5600                 // render the normal view scene and copy into texture
5601                 // (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)
5602                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5603                 {
5604                         r_refdef.view = myview;
5605                         if(r_water_scissormode.integer)
5606                         {
5607                                 R_SetupView(true);
5608                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5609                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5610                         }
5611
5612                         r_waterstate.renderingrefraction = true;
5613
5614                         r_refdef.view.clipplane = p->plane;
5615                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5616                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5617
5618                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5619                         {
5620                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5621                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5622                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5623                                 R_RenderView_UpdateViewVectors();
5624                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5625                                 {
5626                                         r_refdef.view.usecustompvs = true;
5627                                         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);
5628                                 }
5629                         }
5630
5631                         PlaneClassify(&r_refdef.view.clipplane);
5632
5633                         R_ResetViewRendering3D();
5634                         R_ClearScreen(r_refdef.fogenabled);
5635                         if(r_water_scissormode.integer & 2)
5636                                 R_View_UpdateWithScissor(myscissor);
5637                         else
5638                                 R_View_Update();
5639                         if(r_water_scissormode.integer & 1)
5640                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5641                         R_RenderScene();
5642
5643                         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);
5644                         r_waterstate.renderingrefraction = false;
5645                 }
5646                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5647                 {
5648                         r_refdef.view = myview;
5649
5650                         r_refdef.view.clipplane = p->plane;
5651                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5652                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5653
5654                         r_refdef.view.width = r_waterstate.camerawidth;
5655                         r_refdef.view.height = r_waterstate.cameraheight;
5656                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5657                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5658
5659                         if(p->camera_entity)
5660                         {
5661                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5662                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5663                         }
5664
5665                         // note: all of the view is used for displaying... so
5666                         // there is no use in scissoring
5667
5668                         // reverse the cullface settings for this render
5669                         r_refdef.view.cullface_front = GL_FRONT;
5670                         r_refdef.view.cullface_back = GL_BACK;
5671                         // also reverse the view matrix
5672                         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
5673                         R_RenderView_UpdateViewVectors();
5674                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5675                         {
5676                                 r_refdef.view.usecustompvs = true;
5677                                 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);
5678                         }
5679                         
5680                         // camera needs no clipplane
5681                         r_refdef.view.useclipplane = false;
5682
5683                         PlaneClassify(&r_refdef.view.clipplane);
5684
5685                         R_ResetViewRendering3D();
5686                         R_ClearScreen(r_refdef.fogenabled);
5687                         R_View_Update();
5688                         R_RenderScene();
5689
5690                         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);
5691                         r_waterstate.renderingrefraction = false;
5692                 }
5693
5694         }
5695         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5696         r_waterstate.renderingscene = false;
5697         r_refdef.view = originalview;
5698         R_ResetViewRendering3D();
5699         R_ClearScreen(r_refdef.fogenabled);
5700         R_View_Update();
5701         return;
5702 error:
5703         r_refdef.view = originalview;
5704         r_waterstate.renderingscene = false;
5705         Cvar_SetValueQuick(&r_water, 0);
5706         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5707         return;
5708 }
5709
5710 void R_Bloom_StartFrame(void)
5711 {
5712         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5713         int viewwidth, viewheight;
5714         textype_t textype;
5715
5716         if (r_viewscale_fpsscaling.integer)
5717         {
5718                 double actualframetime;
5719                 double targetframetime;
5720                 double adjust;
5721                 actualframetime = r_refdef.lastdrawscreentime;
5722                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5723                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5724                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5725                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5726                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5727                 viewscalefpsadjusted += adjust;
5728                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5729         }
5730         else
5731                 viewscalefpsadjusted = 1.0f;
5732
5733         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5734
5735         switch(vid.renderpath)
5736         {
5737         case RENDERPATH_GL20:
5738         case RENDERPATH_D3D9:
5739         case RENDERPATH_D3D10:
5740         case RENDERPATH_D3D11:
5741         case RENDERPATH_SOFT:
5742         case RENDERPATH_GLES2:
5743                 break;
5744         case RENDERPATH_GL11:
5745         case RENDERPATH_GL13:
5746         case RENDERPATH_GLES1:
5747                 return;
5748         }
5749
5750         // set bloomwidth and bloomheight to the bloom resolution that will be
5751         // used (often less than the screen resolution for faster rendering)
5752         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5753         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5754         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5755         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5756         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5757
5758         // calculate desired texture sizes
5759         if (vid.support.arb_texture_non_power_of_two)
5760         {
5761                 screentexturewidth = vid.width;
5762                 screentextureheight = vid.height;
5763                 bloomtexturewidth = r_bloomstate.bloomwidth;
5764                 bloomtextureheight = r_bloomstate.bloomheight;
5765         }
5766         else
5767         {
5768                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5769                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5770                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5771                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5772         }
5773
5774         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))
5775         {
5776                 Cvar_SetValueQuick(&r_hdr, 0);
5777                 Cvar_SetValueQuick(&r_bloom, 0);
5778                 Cvar_SetValueQuick(&r_motionblur, 0);
5779                 Cvar_SetValueQuick(&r_damageblur, 0);
5780         }
5781
5782         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)
5783                 screentexturewidth = screentextureheight = 0;
5784         if (!r_hdr.integer && !r_bloom.integer)
5785                 bloomtexturewidth = bloomtextureheight = 0;
5786
5787         textype = TEXTYPE_COLORBUFFER;
5788         switch (vid.renderpath)
5789         {
5790         case RENDERPATH_GL20:
5791         case RENDERPATH_GLES2:
5792                 if (vid.support.ext_framebuffer_object)
5793                 {
5794                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5795                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5796                 }
5797                 break;
5798         case RENDERPATH_GL11:
5799         case RENDERPATH_GL13:
5800         case RENDERPATH_GLES1:
5801         case RENDERPATH_D3D9:
5802         case RENDERPATH_D3D10:
5803         case RENDERPATH_D3D11:
5804         case RENDERPATH_SOFT:
5805                 break;
5806         }
5807
5808         // allocate textures as needed
5809         if (r_bloomstate.screentexturewidth != screentexturewidth
5810          || r_bloomstate.screentextureheight != screentextureheight
5811          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5812          || r_bloomstate.bloomtextureheight != bloomtextureheight
5813          || r_bloomstate.texturetype != textype
5814          || r_bloomstate.viewfbo != r_viewfbo.integer)
5815         {
5816                 if (r_bloomstate.texture_bloom)
5817                         R_FreeTexture(r_bloomstate.texture_bloom);
5818                 r_bloomstate.texture_bloom = NULL;
5819                 if (r_bloomstate.texture_screen)
5820                         R_FreeTexture(r_bloomstate.texture_screen);
5821                 r_bloomstate.texture_screen = NULL;
5822                 if (r_bloomstate.fbo_framebuffer)
5823                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5824                 r_bloomstate.fbo_framebuffer = 0;
5825                 if (r_bloomstate.texture_framebuffercolor)
5826                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5827                 r_bloomstate.texture_framebuffercolor = NULL;
5828                 if (r_bloomstate.texture_framebufferdepth)
5829                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5830                 r_bloomstate.texture_framebufferdepth = NULL;
5831                 r_bloomstate.screentexturewidth = screentexturewidth;
5832                 r_bloomstate.screentextureheight = screentextureheight;
5833                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5834                         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);
5835                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5836                 {
5837                         // FIXME: choose depth bits based on a cvar
5838                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5839                         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);
5840                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5841                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5842                         // render depth into one texture and normalmap into the other
5843                         if (qglDrawBuffer)
5844                         {
5845                                 int status;
5846                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5847                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5848                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5849                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5850                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5851                         }
5852                 }
5853                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5854                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5855                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5856                         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);
5857                 r_bloomstate.viewfbo = r_viewfbo.integer;
5858                 r_bloomstate.texturetype = textype;
5859         }
5860
5861         // when doing a reduced render (HDR) we want to use a smaller area
5862         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5863         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5864         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5865         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5866         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5867
5868         // set up a texcoord array for the full resolution screen image
5869         // (we have to keep this around to copy back during final render)
5870         r_bloomstate.screentexcoord2f[0] = 0;
5871         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5872         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5873         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5874         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5875         r_bloomstate.screentexcoord2f[5] = 0;
5876         r_bloomstate.screentexcoord2f[6] = 0;
5877         r_bloomstate.screentexcoord2f[7] = 0;
5878
5879         // set up a texcoord array for the reduced resolution bloom image
5880         // (which will be additive blended over the screen image)
5881         r_bloomstate.bloomtexcoord2f[0] = 0;
5882         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5883         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5884         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5885         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5886         r_bloomstate.bloomtexcoord2f[5] = 0;
5887         r_bloomstate.bloomtexcoord2f[6] = 0;
5888         r_bloomstate.bloomtexcoord2f[7] = 0;
5889
5890         switch(vid.renderpath)
5891         {
5892         case RENDERPATH_GL11:
5893         case RENDERPATH_GL13:
5894         case RENDERPATH_GL20:
5895         case RENDERPATH_SOFT:
5896         case RENDERPATH_GLES1:
5897         case RENDERPATH_GLES2:
5898                 break;
5899         case RENDERPATH_D3D9:
5900         case RENDERPATH_D3D10:
5901         case RENDERPATH_D3D11:
5902                 {
5903                         int i;
5904                         for (i = 0;i < 4;i++)
5905                         {
5906                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5907                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5908                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5909                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5910                         }
5911                 }
5912                 break;
5913         }
5914
5915         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5916         {
5917                 r_bloomstate.enabled = true;
5918                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5919         }
5920
5921         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);
5922
5923         if (r_bloomstate.fbo_framebuffer)
5924                 r_refdef.view.clear = true;
5925 }
5926
5927 void R_Bloom_CopyBloomTexture(float colorscale)
5928 {
5929         r_refdef.stats.bloom++;
5930
5931         // scale down screen texture to the bloom texture size
5932         CHECKGLERROR
5933         R_Mesh_SetMainRenderTargets();
5934         R_SetViewport(&r_bloomstate.viewport);
5935         GL_BlendFunc(GL_ONE, GL_ZERO);
5936         GL_Color(colorscale, colorscale, colorscale, 1);
5937         // 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...
5938         switch(vid.renderpath)
5939         {
5940         case RENDERPATH_GL11:
5941         case RENDERPATH_GL13:
5942         case RENDERPATH_GL20:
5943         case RENDERPATH_GLES1:
5944         case RENDERPATH_GLES2:
5945         case RENDERPATH_SOFT:
5946                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5947                 break;
5948         case RENDERPATH_D3D9:
5949         case RENDERPATH_D3D10:
5950         case RENDERPATH_D3D11:
5951                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5952                 break;
5953         }
5954         // TODO: do boxfilter scale-down in shader?
5955         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5956         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5957         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5958
5959         // we now have a bloom image in the framebuffer
5960         // copy it into the bloom image texture for later processing
5961         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);
5962         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5963 }
5964
5965 void R_Bloom_CopyHDRTexture(void)
5966 {
5967         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);
5968         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5969 }
5970
5971 void R_Bloom_MakeTexture(void)
5972 {
5973         int x, range, dir;
5974         float xoffset, yoffset, r, brighten;
5975
5976         r_refdef.stats.bloom++;
5977
5978         R_ResetViewRendering2D();
5979
5980         // we have a bloom image in the framebuffer
5981         CHECKGLERROR
5982         R_SetViewport(&r_bloomstate.viewport);
5983
5984         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5985         {
5986                 x *= 2;
5987                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5988                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5989                 GL_Color(r,r,r,1);
5990                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5991                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5992                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5993                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5994
5995                 // copy the vertically blurred bloom view to a texture
5996                 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);
5997                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5998         }
5999
6000         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6001         brighten = r_bloom_brighten.value;
6002         if (r_bloomstate.hdr)
6003                 brighten *= r_hdr_range.value;
6004         brighten = sqrt(brighten);
6005         if(range >= 1)
6006                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6007         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6008
6009         for (dir = 0;dir < 2;dir++)
6010         {
6011                 // blend on at multiple vertical offsets to achieve a vertical blur
6012                 // TODO: do offset blends using GLSL
6013                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6014                 GL_BlendFunc(GL_ONE, GL_ZERO);
6015                 for (x = -range;x <= range;x++)
6016                 {
6017                         if (!dir){xoffset = 0;yoffset = x;}
6018                         else {xoffset = x;yoffset = 0;}
6019                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6020                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6021                         // compute a texcoord array with the specified x and y offset
6022                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6023                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6024                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6025                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6026                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6027                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6028                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6029                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6030                         // this r value looks like a 'dot' particle, fading sharply to
6031                         // black at the edges
6032                         // (probably not realistic but looks good enough)
6033                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6034                         //r = brighten/(range*2+1);
6035                         r = brighten / (range * 2 + 1);
6036                         if(range >= 1)
6037                                 r *= (1 - x*x/(float)(range*range));
6038                         GL_Color(r, r, r, 1);
6039                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6040                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6041                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6042                         GL_BlendFunc(GL_ONE, GL_ONE);
6043                 }
6044
6045                 // copy the vertically blurred bloom view to a texture
6046                 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);
6047                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6048         }
6049 }
6050
6051 void R_HDR_RenderBloomTexture(void)
6052 {
6053         int oldwidth, oldheight;
6054         float oldcolorscale;
6055         qboolean oldwaterstate;
6056
6057         oldwaterstate = r_waterstate.enabled;
6058         oldcolorscale = r_refdef.view.colorscale;
6059         oldwidth = r_refdef.view.width;
6060         oldheight = r_refdef.view.height;
6061         r_refdef.view.width = r_bloomstate.bloomwidth;
6062         r_refdef.view.height = r_bloomstate.bloomheight;
6063
6064         if(r_hdr.integer < 2)
6065                 r_waterstate.enabled = false;
6066
6067         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6068         // TODO: add exposure compensation features
6069         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6070
6071         r_refdef.view.showdebug = false;
6072         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6073
6074         R_ResetViewRendering3D();
6075
6076         R_ClearScreen(r_refdef.fogenabled);
6077         if (r_timereport_active)
6078                 R_TimeReport("HDRclear");
6079
6080         R_View_Update();
6081         if (r_timereport_active)
6082                 R_TimeReport("visibility");
6083
6084         // only do secondary renders with HDR if r_hdr is 2 or higher
6085         r_waterstate.numwaterplanes = 0;
6086         if (r_waterstate.enabled)
6087                 R_RenderWaterPlanes();
6088
6089         r_refdef.view.showdebug = true;
6090         R_RenderScene();
6091         r_waterstate.numwaterplanes = 0;
6092
6093         R_ResetViewRendering2D();
6094
6095         R_Bloom_CopyHDRTexture();
6096         R_Bloom_MakeTexture();
6097
6098         // restore the view settings
6099         r_waterstate.enabled = oldwaterstate;
6100         r_refdef.view.width = oldwidth;
6101         r_refdef.view.height = oldheight;
6102         r_refdef.view.colorscale = oldcolorscale;
6103
6104         R_ResetViewRendering3D();
6105
6106         R_ClearScreen(r_refdef.fogenabled);
6107         if (r_timereport_active)
6108                 R_TimeReport("viewclear");
6109 }
6110
6111 static void R_BlendView(void)
6112 {
6113         unsigned int permutation;
6114         float uservecs[4][4];
6115
6116         switch (vid.renderpath)
6117         {
6118         case RENDERPATH_GL20:
6119         case RENDERPATH_D3D9:
6120         case RENDERPATH_D3D10:
6121         case RENDERPATH_D3D11:
6122         case RENDERPATH_SOFT:
6123         case RENDERPATH_GLES2:
6124                 permutation =
6125                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6126                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6127                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6128                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6129                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6130
6131                 if (r_bloomstate.texture_screen)
6132                 {
6133                         // make sure the buffer is available
6134                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6135
6136                         R_ResetViewRendering2D();
6137                         R_Mesh_SetMainRenderTargets();
6138
6139                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6140                         {
6141                                 // declare variables
6142                                 float speed;
6143                                 static float avgspeed;
6144
6145                                 speed = VectorLength(cl.movement_velocity);
6146
6147                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6148                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6149
6150                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6151                                 speed = bound(0, speed, 1);
6152                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6153
6154                                 // calculate values into a standard alpha
6155                                 cl.motionbluralpha = 1 - exp(-
6156                                                 (
6157                                                  (r_motionblur.value * speed / 80)
6158                                                  +
6159                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6160                                                 )
6161                                                 /
6162                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6163                                            );
6164
6165                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6166                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6167                                 // apply the blur
6168                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6169                                 {
6170                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6171                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6172                                         switch(vid.renderpath)
6173                                         {
6174                                         case RENDERPATH_GL11:
6175                                         case RENDERPATH_GL13:
6176                                         case RENDERPATH_GL20:
6177                                         case RENDERPATH_GLES1:
6178                                         case RENDERPATH_GLES2:
6179                                         case RENDERPATH_SOFT:
6180                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6181                                                 break;
6182                                         case RENDERPATH_D3D9:
6183                                         case RENDERPATH_D3D10:
6184                                         case RENDERPATH_D3D11:
6185                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6186                                                 break;
6187                                         }
6188                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6189                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6190                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6191                                 }
6192                         }
6193
6194                         // copy view into the screen texture
6195                         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);
6196                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6197                 }
6198                 else if (!r_bloomstate.texture_bloom)
6199                 {
6200                         // we may still have to do view tint...
6201                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6202                         {
6203                                 // apply a color tint to the whole view
6204                                 R_ResetViewRendering2D();
6205                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6206                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6207                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6208                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6209                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6210                         }
6211                         break; // no screen processing, no bloom, skip it
6212                 }
6213
6214                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6215                 {
6216                         // render simple bloom effect
6217                         // copy the screen and shrink it and darken it for the bloom process
6218                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6219                         // make the bloom texture
6220                         R_Bloom_MakeTexture();
6221                 }
6222
6223 #if _MSC_VER >= 1400
6224 #define sscanf sscanf_s
6225 #endif
6226                 memset(uservecs, 0, sizeof(uservecs));
6227                 if (r_glsl_postprocess_uservec1_enable.integer)
6228                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6229                 if (r_glsl_postprocess_uservec2_enable.integer)
6230                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6231                 if (r_glsl_postprocess_uservec3_enable.integer)
6232                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6233                 if (r_glsl_postprocess_uservec4_enable.integer)
6234                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6235
6236                 R_ResetViewRendering2D();
6237                 GL_Color(1, 1, 1, 1);
6238                 GL_BlendFunc(GL_ONE, GL_ZERO);
6239
6240                 switch(vid.renderpath)
6241                 {
6242                 case RENDERPATH_GL20:
6243                 case RENDERPATH_GLES2:
6244                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6245                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6246                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6247                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6248                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6249                         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]);
6250                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6251                         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]);
6252                         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]);
6253                         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]);
6254                         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]);
6255                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6256                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6257                         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);
6258                         break;
6259                 case RENDERPATH_D3D9:
6260 #ifdef SUPPORTD3D
6261                         // 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...
6262                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6263                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6264                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6265                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6266                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6267                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6268                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6269                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6270                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6271                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6272                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6273                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6274                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6275                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6276 #endif
6277                         break;
6278                 case RENDERPATH_D3D10:
6279                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6280                         break;
6281                 case RENDERPATH_D3D11:
6282                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6283                         break;
6284                 case RENDERPATH_SOFT:
6285                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6286                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6287                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6288                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6289                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6290                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6291                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6292                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6293                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6294                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6295                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6296                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6297                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6298                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6299                         break;
6300                 default:
6301                         break;
6302                 }
6303                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6304                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6305                 break;
6306         case RENDERPATH_GL11:
6307         case RENDERPATH_GL13:
6308         case RENDERPATH_GLES1:
6309                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6310                 {
6311                         // apply a color tint to the whole view
6312                         R_ResetViewRendering2D();
6313                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6314                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6315                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6316                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6317                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6318                 }
6319                 break;
6320         }
6321 }
6322
6323 matrix4x4_t r_waterscrollmatrix;
6324
6325 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6326 {
6327         if (r_refdef.fog_density)
6328         {
6329                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6330                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6331                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6332
6333                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6334                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6335                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6336                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6337
6338                 {
6339                         vec3_t fogvec;
6340                         VectorCopy(r_refdef.fogcolor, fogvec);
6341                         //   color.rgb *= ContrastBoost * SceneBrightness;
6342                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6343                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6344                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6345                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6346                 }
6347         }
6348 }
6349
6350 void R_UpdateVariables(void)
6351 {
6352         R_Textures_Frame();
6353
6354         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6355
6356         r_refdef.farclip = r_farclip_base.value;
6357         if (r_refdef.scene.worldmodel)
6358                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6359         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6360
6361         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6362                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6363         r_refdef.polygonfactor = 0;
6364         r_refdef.polygonoffset = 0;
6365         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6366         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6367
6368         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6369         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6370         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6371         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6372         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6373         if (FAKELIGHT_ENABLED)
6374         {
6375                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6376         }
6377         if (r_showsurfaces.integer)
6378         {
6379                 r_refdef.scene.rtworld = false;
6380                 r_refdef.scene.rtworldshadows = false;
6381                 r_refdef.scene.rtdlight = false;
6382                 r_refdef.scene.rtdlightshadows = false;
6383                 r_refdef.lightmapintensity = 0;
6384         }
6385
6386         if (gamemode == GAME_NEHAHRA)
6387         {
6388                 if (gl_fogenable.integer)
6389                 {
6390                         r_refdef.oldgl_fogenable = true;
6391                         r_refdef.fog_density = gl_fogdensity.value;
6392                         r_refdef.fog_red = gl_fogred.value;
6393                         r_refdef.fog_green = gl_foggreen.value;
6394                         r_refdef.fog_blue = gl_fogblue.value;
6395                         r_refdef.fog_alpha = 1;
6396                         r_refdef.fog_start = 0;
6397                         r_refdef.fog_end = gl_skyclip.value;
6398                         r_refdef.fog_height = 1<<30;
6399                         r_refdef.fog_fadedepth = 128;
6400                 }
6401                 else if (r_refdef.oldgl_fogenable)
6402                 {
6403                         r_refdef.oldgl_fogenable = false;
6404                         r_refdef.fog_density = 0;
6405                         r_refdef.fog_red = 0;
6406                         r_refdef.fog_green = 0;
6407                         r_refdef.fog_blue = 0;
6408                         r_refdef.fog_alpha = 0;
6409                         r_refdef.fog_start = 0;
6410                         r_refdef.fog_end = 0;
6411                         r_refdef.fog_height = 1<<30;
6412                         r_refdef.fog_fadedepth = 128;
6413                 }
6414         }
6415
6416         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6417         r_refdef.fog_start = max(0, r_refdef.fog_start);
6418         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6419
6420         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6421
6422         if (r_refdef.fog_density && r_drawfog.integer)
6423         {
6424                 r_refdef.fogenabled = true;
6425                 // this is the point where the fog reaches 0.9986 alpha, which we
6426                 // consider a good enough cutoff point for the texture
6427                 // (0.9986 * 256 == 255.6)
6428                 if (r_fog_exp2.integer)
6429                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6430                 else
6431                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6432                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6433                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6434                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6435                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6436                         R_BuildFogHeightTexture();
6437                 // fog color was already set
6438                 // update the fog texture
6439                 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)
6440                         R_BuildFogTexture();
6441                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6442                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6443         }
6444         else
6445                 r_refdef.fogenabled = false;
6446
6447         switch(vid.renderpath)
6448         {
6449         case RENDERPATH_GL20:
6450         case RENDERPATH_D3D9:
6451         case RENDERPATH_D3D10:
6452         case RENDERPATH_D3D11:
6453         case RENDERPATH_SOFT:
6454         case RENDERPATH_GLES2:
6455                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6456                 {
6457                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6458                         {
6459                                 // build GLSL gamma texture
6460 #define RAMPWIDTH 256
6461                                 unsigned short ramp[RAMPWIDTH * 3];
6462                                 unsigned char rampbgr[RAMPWIDTH][4];
6463                                 int i;
6464
6465                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6466
6467                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6468                                 for(i = 0; i < RAMPWIDTH; ++i)
6469                                 {
6470                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6471                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6472                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6473                                         rampbgr[i][3] = 0;
6474                                 }
6475                                 if (r_texture_gammaramps)
6476                                 {
6477                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6478                                 }
6479                                 else
6480                                 {
6481                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6482                                 }
6483                         }
6484                 }
6485                 else
6486                 {
6487                         // remove GLSL gamma texture
6488                 }
6489                 break;
6490         case RENDERPATH_GL11:
6491         case RENDERPATH_GL13:
6492         case RENDERPATH_GLES1:
6493                 break;
6494         }
6495 }
6496
6497 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6498 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6499 /*
6500 ================
6501 R_SelectScene
6502 ================
6503 */
6504 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6505         if( scenetype != r_currentscenetype ) {
6506                 // store the old scenetype
6507                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6508                 r_currentscenetype = scenetype;
6509                 // move in the new scene
6510                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6511         }
6512 }
6513
6514 /*
6515 ================
6516 R_GetScenePointer
6517 ================
6518 */
6519 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6520 {
6521         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6522         if( scenetype == r_currentscenetype ) {
6523                 return &r_refdef.scene;
6524         } else {
6525                 return &r_scenes_store[ scenetype ];
6526         }
6527 }
6528
6529 /*
6530 ================
6531 R_RenderView
6532 ================
6533 */
6534 int dpsoftrast_test;
6535 void R_RenderView(void)
6536 {
6537         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6538
6539         dpsoftrast_test = r_test.integer;
6540
6541         if (r_timereport_active)
6542                 R_TimeReport("start");
6543         r_textureframe++; // used only by R_GetCurrentTexture
6544         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6545
6546         if(R_CompileShader_CheckStaticParms())
6547                 R_GLSL_Restart_f();
6548
6549         if (!r_drawentities.integer)
6550                 r_refdef.scene.numentities = 0;
6551
6552         R_AnimCache_ClearCache();
6553         R_FrameData_NewFrame();
6554
6555         /* adjust for stereo display */
6556         if(R_Stereo_Active())
6557         {
6558                 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);
6559                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6560         }
6561
6562         if (r_refdef.view.isoverlay)
6563         {
6564                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6565                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6566                 R_TimeReport("depthclear");
6567
6568                 r_refdef.view.showdebug = false;
6569
6570                 r_waterstate.enabled = false;
6571                 r_waterstate.numwaterplanes = 0;
6572
6573                 R_RenderScene();
6574
6575                 r_refdef.view.matrix = originalmatrix;
6576
6577                 CHECKGLERROR
6578                 return;
6579         }
6580
6581         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6582         {
6583                 r_refdef.view.matrix = originalmatrix;
6584                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6585         }
6586
6587         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6588
6589         R_RenderView_UpdateViewVectors();
6590
6591         R_Shadow_UpdateWorldLightSelection();
6592
6593         R_Bloom_StartFrame();
6594         R_Water_StartFrame();
6595
6596         CHECKGLERROR
6597         if (r_timereport_active)
6598                 R_TimeReport("viewsetup");
6599
6600         R_ResetViewRendering3D();
6601
6602         if (r_refdef.view.clear || r_refdef.fogenabled)
6603         {
6604                 R_ClearScreen(r_refdef.fogenabled);
6605                 if (r_timereport_active)
6606                         R_TimeReport("viewclear");
6607         }
6608         r_refdef.view.clear = true;
6609
6610         // this produces a bloom texture to be used in R_BlendView() later
6611         if (r_bloomstate.hdr)
6612         {
6613                 R_HDR_RenderBloomTexture();
6614                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6615                 r_textureframe++; // used only by R_GetCurrentTexture
6616         }
6617
6618         r_refdef.view.showdebug = true;
6619
6620         R_View_Update();
6621         if (r_timereport_active)
6622                 R_TimeReport("visibility");
6623
6624         r_waterstate.numwaterplanes = 0;
6625         if (r_waterstate.enabled)
6626                 R_RenderWaterPlanes();
6627
6628         R_RenderScene();
6629         r_waterstate.numwaterplanes = 0;
6630
6631         R_BlendView();
6632         if (r_timereport_active)
6633                 R_TimeReport("blendview");
6634
6635         GL_Scissor(0, 0, vid.width, vid.height);
6636         GL_ScissorTest(false);
6637
6638         r_refdef.view.matrix = originalmatrix;
6639
6640         CHECKGLERROR
6641 }
6642
6643 void R_RenderWaterPlanes(void)
6644 {
6645         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6646         {
6647                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6648                 if (r_timereport_active)
6649                         R_TimeReport("waterworld");
6650         }
6651
6652         // don't let sound skip if going slow
6653         if (r_refdef.scene.extraupdate)
6654                 S_ExtraUpdate ();
6655
6656         R_DrawModelsAddWaterPlanes();
6657         if (r_timereport_active)
6658                 R_TimeReport("watermodels");
6659
6660         if (r_waterstate.numwaterplanes)
6661         {
6662                 R_Water_ProcessPlanes();
6663                 if (r_timereport_active)
6664                         R_TimeReport("waterscenes");
6665         }
6666 }
6667
6668 extern void R_DrawLightningBeams (void);
6669 extern void VM_CL_AddPolygonsToMeshQueue (void);
6670 extern void R_DrawPortals (void);
6671 extern cvar_t cl_locs_show;
6672 static void R_DrawLocs(void);
6673 static void R_DrawEntityBBoxes(void);
6674 static void R_DrawModelDecals(void);
6675 extern void R_DrawModelShadows(void);
6676 extern void R_DrawModelShadowMaps(void);
6677 extern cvar_t cl_decals_newsystem;
6678 extern qboolean r_shadow_usingdeferredprepass;
6679 void R_RenderScene(void)
6680 {
6681         qboolean shadowmapping = false;
6682
6683         if (r_timereport_active)
6684                 R_TimeReport("beginscene");
6685
6686         r_refdef.stats.renders++;
6687
6688         R_UpdateFogColor();
6689
6690         // don't let sound skip if going slow
6691         if (r_refdef.scene.extraupdate)
6692                 S_ExtraUpdate ();
6693
6694         R_MeshQueue_BeginScene();
6695
6696         R_SkyStartFrame();
6697
6698         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);
6699
6700         if (r_timereport_active)
6701                 R_TimeReport("skystartframe");
6702
6703         if (cl.csqc_vidvars.drawworld)
6704         {
6705                 // don't let sound skip if going slow
6706                 if (r_refdef.scene.extraupdate)
6707                         S_ExtraUpdate ();
6708
6709                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6710                 {
6711                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6712                         if (r_timereport_active)
6713                                 R_TimeReport("worldsky");
6714                 }
6715
6716                 if (R_DrawBrushModelsSky() && r_timereport_active)
6717                         R_TimeReport("bmodelsky");
6718
6719                 if (skyrendermasked && skyrenderlater)
6720                 {
6721                         // we have to force off the water clipping plane while rendering sky
6722                         R_SetupView(false);
6723                         R_Sky();
6724                         R_SetupView(true);
6725                         if (r_timereport_active)
6726                                 R_TimeReport("sky");
6727                 }
6728         }
6729
6730         R_AnimCache_CacheVisibleEntities();
6731         if (r_timereport_active)
6732                 R_TimeReport("animation");
6733
6734         R_Shadow_PrepareLights();
6735         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6736                 R_Shadow_PrepareModelShadows();
6737         if (r_timereport_active)
6738                 R_TimeReport("preparelights");
6739
6740         if (R_Shadow_ShadowMappingEnabled())
6741                 shadowmapping = true;
6742
6743         if (r_shadow_usingdeferredprepass)
6744                 R_Shadow_DrawPrepass();
6745
6746         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6747         {
6748                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6749                 if (r_timereport_active)
6750                         R_TimeReport("worlddepth");
6751         }
6752         if (r_depthfirst.integer >= 2)
6753         {
6754                 R_DrawModelsDepth();
6755                 if (r_timereport_active)
6756                         R_TimeReport("modeldepth");
6757         }
6758
6759         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6760         {
6761                 R_DrawModelShadowMaps();
6762                 R_ResetViewRendering3D();
6763                 // don't let sound skip if going slow
6764                 if (r_refdef.scene.extraupdate)
6765                         S_ExtraUpdate ();
6766         }
6767
6768         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6769         {
6770                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6771                 if (r_timereport_active)
6772                         R_TimeReport("world");
6773         }
6774
6775         // don't let sound skip if going slow
6776         if (r_refdef.scene.extraupdate)
6777                 S_ExtraUpdate ();
6778
6779         R_DrawModels();
6780         if (r_timereport_active)
6781                 R_TimeReport("models");
6782
6783         // don't let sound skip if going slow
6784         if (r_refdef.scene.extraupdate)
6785                 S_ExtraUpdate ();
6786
6787         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6788         {
6789                 R_DrawModelShadows();
6790                 R_ResetViewRendering3D();
6791                 // don't let sound skip if going slow
6792                 if (r_refdef.scene.extraupdate)
6793                         S_ExtraUpdate ();
6794         }
6795
6796         if (!r_shadow_usingdeferredprepass)
6797         {
6798                 R_Shadow_DrawLights();
6799                 if (r_timereport_active)
6800                         R_TimeReport("rtlights");
6801         }
6802
6803         // don't let sound skip if going slow
6804         if (r_refdef.scene.extraupdate)
6805                 S_ExtraUpdate ();
6806
6807         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6808         {
6809                 R_DrawModelShadows();
6810                 R_ResetViewRendering3D();
6811                 // don't let sound skip if going slow
6812                 if (r_refdef.scene.extraupdate)
6813                         S_ExtraUpdate ();
6814         }
6815
6816         if (cl.csqc_vidvars.drawworld)
6817         {
6818                 if (cl_decals_newsystem.integer)
6819                 {
6820                         R_DrawModelDecals();
6821                         if (r_timereport_active)
6822                                 R_TimeReport("modeldecals");
6823                 }
6824                 else
6825                 {
6826                         R_DrawDecals();
6827                         if (r_timereport_active)
6828                                 R_TimeReport("decals");
6829                 }
6830
6831                 R_DrawParticles();
6832                 if (r_timereport_active)
6833                         R_TimeReport("particles");
6834
6835                 R_DrawExplosions();
6836                 if (r_timereport_active)
6837                         R_TimeReport("explosions");
6838
6839                 R_DrawLightningBeams();
6840                 if (r_timereport_active)
6841                         R_TimeReport("lightning");
6842         }
6843
6844         VM_CL_AddPolygonsToMeshQueue();
6845
6846         if (r_refdef.view.showdebug)
6847         {
6848                 if (cl_locs_show.integer)
6849                 {
6850                         R_DrawLocs();
6851                         if (r_timereport_active)
6852                                 R_TimeReport("showlocs");
6853                 }
6854
6855                 if (r_drawportals.integer)
6856                 {
6857                         R_DrawPortals();
6858                         if (r_timereport_active)
6859                                 R_TimeReport("portals");
6860                 }
6861
6862                 if (r_showbboxes.value > 0)
6863                 {
6864                         R_DrawEntityBBoxes();
6865                         if (r_timereport_active)
6866                                 R_TimeReport("bboxes");
6867                 }
6868         }
6869
6870         R_MeshQueue_RenderTransparent();
6871         if (r_timereport_active)
6872                 R_TimeReport("drawtrans");
6873
6874         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))
6875         {
6876                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6877                 if (r_timereport_active)
6878                         R_TimeReport("worlddebug");
6879                 R_DrawModelsDebug();
6880                 if (r_timereport_active)
6881                         R_TimeReport("modeldebug");
6882         }
6883
6884         if (cl.csqc_vidvars.drawworld)
6885         {
6886                 R_Shadow_DrawCoronas();
6887                 if (r_timereport_active)
6888                         R_TimeReport("coronas");
6889         }
6890
6891 #if 0
6892         {
6893                 GL_DepthTest(false);
6894                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6895                 GL_Color(1, 1, 1, 1);
6896                 qglBegin(GL_POLYGON);
6897                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6898                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6899                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6900                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6901                 qglEnd();
6902                 qglBegin(GL_POLYGON);
6903                 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]);
6904                 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]);
6905                 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]);
6906                 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]);
6907                 qglEnd();
6908                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6909         }
6910 #endif
6911
6912         // don't let sound skip if going slow
6913         if (r_refdef.scene.extraupdate)
6914                 S_ExtraUpdate ();
6915
6916         R_ResetViewRendering2D();
6917 }
6918
6919 static const unsigned short bboxelements[36] =
6920 {
6921         5, 1, 3, 5, 3, 7,
6922         6, 2, 0, 6, 0, 4,
6923         7, 3, 2, 7, 2, 6,
6924         4, 0, 1, 4, 1, 5,
6925         4, 5, 7, 4, 7, 6,
6926         1, 0, 2, 1, 2, 3,
6927 };
6928
6929 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6930 {
6931         int i;
6932         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6933
6934         RSurf_ActiveWorldEntity();
6935
6936         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6937         GL_DepthMask(false);
6938         GL_DepthRange(0, 1);
6939         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6940 //      R_Mesh_ResetTextureState();
6941
6942         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6943         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6944         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6945         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6946         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6947         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6948         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6949         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6950         R_FillColors(color4f, 8, cr, cg, cb, ca);
6951         if (r_refdef.fogenabled)
6952         {
6953                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6954                 {
6955                         f1 = RSurf_FogVertex(v);
6956                         f2 = 1 - f1;
6957                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6958                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6959                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6960                 }
6961         }
6962         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6963         R_Mesh_ResetTextureState();
6964         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6965         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6966 }
6967
6968 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6969 {
6970         int i;
6971         float color[4];
6972         prvm_edict_t *edict;
6973         prvm_prog_t *prog_save = prog;
6974
6975         // this function draws bounding boxes of server entities
6976         if (!sv.active)
6977                 return;
6978
6979         GL_CullFace(GL_NONE);
6980         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6981
6982         prog = 0;
6983         SV_VM_Begin();
6984         for (i = 0;i < numsurfaces;i++)
6985         {
6986                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6987                 switch ((int)edict->fields.server->solid)
6988                 {
6989                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6990                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6991                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6992                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6993                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6994                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6995                 }
6996                 color[3] *= r_showbboxes.value;
6997                 color[3] = bound(0, color[3], 1);
6998                 GL_DepthTest(!r_showdisabledepthtest.integer);
6999                 GL_CullFace(r_refdef.view.cullface_front);
7000                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7001         }
7002         SV_VM_End();
7003         prog = prog_save;
7004 }
7005
7006 static void R_DrawEntityBBoxes(void)
7007 {
7008         int i;
7009         prvm_edict_t *edict;
7010         vec3_t center;
7011         prvm_prog_t *prog_save = prog;
7012
7013         // this function draws bounding boxes of server entities
7014         if (!sv.active)
7015                 return;
7016
7017         prog = 0;
7018         SV_VM_Begin();
7019         for (i = 0;i < prog->num_edicts;i++)
7020         {
7021                 edict = PRVM_EDICT_NUM(i);
7022                 if (edict->priv.server->free)
7023                         continue;
7024                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7025                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7026                         continue;
7027                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7028                         continue;
7029                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7030                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7031         }
7032         SV_VM_End();
7033         prog = prog_save;
7034 }
7035
7036 static const int nomodelelement3i[24] =
7037 {
7038         5, 2, 0,
7039         5, 1, 2,
7040         5, 0, 3,
7041         5, 3, 1,
7042         0, 2, 4,
7043         2, 1, 4,
7044         3, 0, 4,
7045         1, 3, 4
7046 };
7047
7048 static const unsigned short nomodelelement3s[24] =
7049 {
7050         5, 2, 0,
7051         5, 1, 2,
7052         5, 0, 3,
7053         5, 3, 1,
7054         0, 2, 4,
7055         2, 1, 4,
7056         3, 0, 4,
7057         1, 3, 4
7058 };
7059
7060 static const float nomodelvertex3f[6*3] =
7061 {
7062         -16,   0,   0,
7063          16,   0,   0,
7064           0, -16,   0,
7065           0,  16,   0,
7066           0,   0, -16,
7067           0,   0,  16
7068 };
7069
7070 static const float nomodelcolor4f[6*4] =
7071 {
7072         0.0f, 0.0f, 0.5f, 1.0f,
7073         0.0f, 0.0f, 0.5f, 1.0f,
7074         0.0f, 0.5f, 0.0f, 1.0f,
7075         0.0f, 0.5f, 0.0f, 1.0f,
7076         0.5f, 0.0f, 0.0f, 1.0f,
7077         0.5f, 0.0f, 0.0f, 1.0f
7078 };
7079
7080 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7081 {
7082         int i;
7083         float f1, f2, *c;
7084         float color4f[6*4];
7085
7086         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);
7087
7088         // this is only called once per entity so numsurfaces is always 1, and
7089         // surfacelist is always {0}, so this code does not handle batches
7090
7091         if (rsurface.ent_flags & RENDER_ADDITIVE)
7092         {
7093                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7094                 GL_DepthMask(false);
7095         }
7096         else if (rsurface.colormod[3] < 1)
7097         {
7098                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7099                 GL_DepthMask(false);
7100         }
7101         else
7102         {
7103                 GL_BlendFunc(GL_ONE, GL_ZERO);
7104                 GL_DepthMask(true);
7105         }
7106         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7107         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7108         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7109         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7110         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7111         for (i = 0, c = color4f;i < 6;i++, c += 4)
7112         {
7113                 c[0] *= rsurface.colormod[0];
7114                 c[1] *= rsurface.colormod[1];
7115                 c[2] *= rsurface.colormod[2];
7116                 c[3] *= rsurface.colormod[3];
7117         }
7118         if (r_refdef.fogenabled)
7119         {
7120                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7121                 {
7122                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7123                         f2 = 1 - f1;
7124                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7125                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7126                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7127                 }
7128         }
7129 //      R_Mesh_ResetTextureState();
7130         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7131         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7132         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7133 }
7134
7135 void R_DrawNoModel(entity_render_t *ent)
7136 {
7137         vec3_t org;
7138         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7139         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7140                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7141         else
7142                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7143 }
7144
7145 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7146 {
7147         vec3_t right1, right2, diff, normal;
7148
7149         VectorSubtract (org2, org1, normal);
7150
7151         // calculate 'right' vector for start
7152         VectorSubtract (r_refdef.view.origin, org1, diff);
7153         CrossProduct (normal, diff, right1);
7154         VectorNormalize (right1);
7155
7156         // calculate 'right' vector for end
7157         VectorSubtract (r_refdef.view.origin, org2, diff);
7158         CrossProduct (normal, diff, right2);
7159         VectorNormalize (right2);
7160
7161         vert[ 0] = org1[0] + width * right1[0];
7162         vert[ 1] = org1[1] + width * right1[1];
7163         vert[ 2] = org1[2] + width * right1[2];
7164         vert[ 3] = org1[0] - width * right1[0];
7165         vert[ 4] = org1[1] - width * right1[1];
7166         vert[ 5] = org1[2] - width * right1[2];
7167         vert[ 6] = org2[0] - width * right2[0];
7168         vert[ 7] = org2[1] - width * right2[1];
7169         vert[ 8] = org2[2] - width * right2[2];
7170         vert[ 9] = org2[0] + width * right2[0];
7171         vert[10] = org2[1] + width * right2[1];
7172         vert[11] = org2[2] + width * right2[2];
7173 }
7174
7175 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)
7176 {
7177         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7178         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7179         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7180         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7181         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7182         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7183         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7184         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7185         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7186         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7187         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7188         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7189 }
7190
7191 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7192 {
7193         int i;
7194         float *vertex3f;
7195         float v[3];
7196         VectorSet(v, x, y, z);
7197         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7198                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7199                         break;
7200         if (i == mesh->numvertices)
7201         {
7202                 if (mesh->numvertices < mesh->maxvertices)
7203                 {
7204                         VectorCopy(v, vertex3f);
7205                         mesh->numvertices++;
7206                 }
7207                 return mesh->numvertices;
7208         }
7209         else
7210                 return i;
7211 }
7212
7213 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7214 {
7215         int i;
7216         int *e, element[3];
7217         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7218         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7219         e = mesh->element3i + mesh->numtriangles * 3;
7220         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7221         {
7222                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7223                 if (mesh->numtriangles < mesh->maxtriangles)
7224                 {
7225                         *e++ = element[0];
7226                         *e++ = element[1];
7227                         *e++ = element[2];
7228                         mesh->numtriangles++;
7229                 }
7230                 element[1] = element[2];
7231         }
7232 }
7233
7234 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7235 {
7236         int i;
7237         int *e, element[3];
7238         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7239         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7240         e = mesh->element3i + mesh->numtriangles * 3;
7241         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7242         {
7243                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7244                 if (mesh->numtriangles < mesh->maxtriangles)
7245                 {
7246                         *e++ = element[0];
7247                         *e++ = element[1];
7248                         *e++ = element[2];
7249                         mesh->numtriangles++;
7250                 }
7251                 element[1] = element[2];
7252         }
7253 }
7254
7255 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7256 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7257 {
7258         int planenum, planenum2;
7259         int w;
7260         int tempnumpoints;
7261         mplane_t *plane, *plane2;
7262         double maxdist;
7263         double temppoints[2][256*3];
7264         // figure out how large a bounding box we need to properly compute this brush
7265         maxdist = 0;
7266         for (w = 0;w < numplanes;w++)
7267                 maxdist = max(maxdist, fabs(planes[w].dist));
7268         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7269         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7270         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7271         {
7272                 w = 0;
7273                 tempnumpoints = 4;
7274                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7275                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7276                 {
7277                         if (planenum2 == planenum)
7278                                 continue;
7279                         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);
7280                         w = !w;
7281                 }
7282                 if (tempnumpoints < 3)
7283                         continue;
7284                 // generate elements forming a triangle fan for this polygon
7285                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7286         }
7287 }
7288
7289 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)
7290 {
7291         texturelayer_t *layer;
7292         layer = t->currentlayers + t->currentnumlayers++;
7293         layer->type = type;
7294         layer->depthmask = depthmask;
7295         layer->blendfunc1 = blendfunc1;
7296         layer->blendfunc2 = blendfunc2;
7297         layer->texture = texture;
7298         layer->texmatrix = *matrix;
7299         layer->color[0] = r;
7300         layer->color[1] = g;
7301         layer->color[2] = b;
7302         layer->color[3] = a;
7303 }
7304
7305 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7306 {
7307         if(parms[0] == 0 && parms[1] == 0)
7308                 return false;
7309         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7310                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7311                         return false;
7312         return true;
7313 }
7314
7315 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7316 {
7317         double index, f;
7318         index = parms[2] + r_refdef.scene.time * parms[3];
7319         index -= floor(index);
7320         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7321         {
7322         default:
7323         case Q3WAVEFUNC_NONE:
7324         case Q3WAVEFUNC_NOISE:
7325         case Q3WAVEFUNC_COUNT:
7326                 f = 0;
7327                 break;
7328         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7329         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7330         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7331         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7332         case Q3WAVEFUNC_TRIANGLE:
7333                 index *= 4;
7334                 f = index - floor(index);
7335                 if (index < 1)
7336                         f = f;
7337                 else if (index < 2)
7338                         f = 1 - f;
7339                 else if (index < 3)
7340                         f = -f;
7341                 else
7342                         f = -(1 - f);
7343                 break;
7344         }
7345         f = parms[0] + parms[1] * f;
7346         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7347                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7348         return (float) f;
7349 }
7350
7351 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7352 {
7353         int w, h, idx;
7354         float f;
7355         float tcmat[12];
7356         matrix4x4_t matrix, temp;
7357         switch(tcmod->tcmod)
7358         {
7359                 case Q3TCMOD_COUNT:
7360                 case Q3TCMOD_NONE:
7361                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7362                                 matrix = r_waterscrollmatrix;
7363                         else
7364                                 matrix = identitymatrix;
7365                         break;
7366                 case Q3TCMOD_ENTITYTRANSLATE:
7367                         // this is used in Q3 to allow the gamecode to control texcoord
7368                         // scrolling on the entity, which is not supported in darkplaces yet.
7369                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7370                         break;
7371                 case Q3TCMOD_ROTATE:
7372                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7373                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7374                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7375                         break;
7376                 case Q3TCMOD_SCALE:
7377                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7378                         break;
7379                 case Q3TCMOD_SCROLL:
7380                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7381                         break;
7382                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7383                         w = (int) tcmod->parms[0];
7384                         h = (int) tcmod->parms[1];
7385                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7386                         f = f - floor(f);
7387                         idx = (int) floor(f * w * h);
7388                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7389                         break;
7390                 case Q3TCMOD_STRETCH:
7391                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7392                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7393                         break;
7394                 case Q3TCMOD_TRANSFORM:
7395                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7396                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7397                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7398                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7399                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7400                         break;
7401                 case Q3TCMOD_TURBULENT:
7402                         // this is handled in the RSurf_PrepareVertices function
7403                         matrix = identitymatrix;
7404                         break;
7405         }
7406         temp = *texmatrix;
7407         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7408 }
7409
7410 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7411 {
7412         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7413         char name[MAX_QPATH];
7414         skinframe_t *skinframe;
7415         unsigned char pixels[296*194];
7416         strlcpy(cache->name, skinname, sizeof(cache->name));
7417         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7418         if (developer_loading.integer)
7419                 Con_Printf("loading %s\n", name);
7420         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7421         if (!skinframe || !skinframe->base)
7422         {
7423                 unsigned char *f;
7424                 fs_offset_t filesize;
7425                 skinframe = NULL;
7426                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7427                 if (f)
7428                 {
7429                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7430                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7431                         Mem_Free(f);
7432                 }
7433         }
7434         cache->skinframe = skinframe;
7435 }
7436
7437 texture_t *R_GetCurrentTexture(texture_t *t)
7438 {
7439         int i;
7440         const entity_render_t *ent = rsurface.entity;
7441         dp_model_t *model = ent->model;
7442         q3shaderinfo_layer_tcmod_t *tcmod;
7443
7444         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7445                 return t->currentframe;
7446         t->update_lastrenderframe = r_textureframe;
7447         t->update_lastrenderentity = (void *)ent;
7448
7449         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7450                 t->camera_entity = ent->entitynumber;
7451         else
7452                 t->camera_entity = 0;
7453
7454         // switch to an alternate material if this is a q1bsp animated material
7455         {
7456                 texture_t *texture = t;
7457                 int s = rsurface.ent_skinnum;
7458                 if ((unsigned int)s >= (unsigned int)model->numskins)
7459                         s = 0;
7460                 if (model->skinscenes)
7461                 {
7462                         if (model->skinscenes[s].framecount > 1)
7463                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7464                         else
7465                                 s = model->skinscenes[s].firstframe;
7466                 }
7467                 if (s > 0)
7468                         t = t + s * model->num_surfaces;
7469                 if (t->animated)
7470                 {
7471                         // use an alternate animation if the entity's frame is not 0,
7472                         // and only if the texture has an alternate animation
7473                         if (rsurface.ent_alttextures && t->anim_total[1])
7474                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7475                         else
7476                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7477                 }
7478                 texture->currentframe = t;
7479         }
7480
7481         // update currentskinframe to be a qw skin or animation frame
7482         if (rsurface.ent_qwskin >= 0)
7483         {
7484                 i = rsurface.ent_qwskin;
7485                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7486                 {
7487                         r_qwskincache_size = cl.maxclients;
7488                         if (r_qwskincache)
7489                                 Mem_Free(r_qwskincache);
7490                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7491                 }
7492                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7493                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7494                 t->currentskinframe = r_qwskincache[i].skinframe;
7495                 if (t->currentskinframe == NULL)
7496                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7497         }
7498         else if (t->numskinframes >= 2)
7499                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7500         if (t->backgroundnumskinframes >= 2)
7501                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7502
7503         t->currentmaterialflags = t->basematerialflags;
7504         t->currentalpha = rsurface.colormod[3];
7505         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7506                 t->currentalpha *= r_wateralpha.value;
7507         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7508                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7509         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7510                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7511         if (!(rsurface.ent_flags & RENDER_LIGHT))
7512                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7513         else if (FAKELIGHT_ENABLED)
7514         {
7515                         // no modellight if using fakelight for the map
7516         }
7517         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7518         {
7519                 // pick a model lighting mode
7520                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7521                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7522                 else
7523                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7524         }
7525         if (rsurface.ent_flags & RENDER_ADDITIVE)
7526                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7527         else if (t->currentalpha < 1)
7528                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7529         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7530                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7531         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7532                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7533         if (t->backgroundnumskinframes)
7534                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7535         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7536         {
7537                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7538                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7539         }
7540         else
7541                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7542         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7543                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7544
7545         // there is no tcmod
7546         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7547         {
7548                 t->currenttexmatrix = r_waterscrollmatrix;
7549                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7550         }
7551         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7552         {
7553                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7554                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7555         }
7556
7557         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7558                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7559         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7560                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7561
7562         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7563         if (t->currentskinframe->qpixels)
7564                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7565         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7566         if (!t->basetexture)
7567                 t->basetexture = r_texture_notexture;
7568         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7569         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7570         t->nmaptexture = t->currentskinframe->nmap;
7571         if (!t->nmaptexture)
7572                 t->nmaptexture = r_texture_blanknormalmap;
7573         t->glosstexture = r_texture_black;
7574         t->glowtexture = t->currentskinframe->glow;
7575         t->fogtexture = t->currentskinframe->fog;
7576         t->reflectmasktexture = t->currentskinframe->reflect;
7577         if (t->backgroundnumskinframes)
7578         {
7579                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7580                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7581                 t->backgroundglosstexture = r_texture_black;
7582                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7583                 if (!t->backgroundnmaptexture)
7584                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7585         }
7586         else
7587         {
7588                 t->backgroundbasetexture = r_texture_white;
7589                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7590                 t->backgroundglosstexture = r_texture_black;
7591                 t->backgroundglowtexture = NULL;
7592         }
7593         t->specularpower = r_shadow_glossexponent.value;
7594         // TODO: store reference values for these in the texture?
7595         t->specularscale = 0;
7596         if (r_shadow_gloss.integer > 0)
7597         {
7598                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7599                 {
7600                         if (r_shadow_glossintensity.value > 0)
7601                         {
7602                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7603                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7604                                 t->specularscale = r_shadow_glossintensity.value;
7605                         }
7606                 }
7607                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7608                 {
7609                         t->glosstexture = r_texture_white;
7610                         t->backgroundglosstexture = r_texture_white;
7611                         t->specularscale = r_shadow_gloss2intensity.value;
7612                         t->specularpower = r_shadow_gloss2exponent.value;
7613                 }
7614         }
7615         t->specularscale *= t->specularscalemod;
7616         t->specularpower *= t->specularpowermod;
7617
7618         // lightmaps mode looks bad with dlights using actual texturing, so turn
7619         // off the colormap and glossmap, but leave the normalmap on as it still
7620         // accurately represents the shading involved
7621         if (gl_lightmaps.integer)
7622         {
7623                 t->basetexture = r_texture_grey128;
7624                 t->pantstexture = r_texture_black;
7625                 t->shirttexture = r_texture_black;
7626                 t->nmaptexture = r_texture_blanknormalmap;
7627                 t->glosstexture = r_texture_black;
7628                 t->glowtexture = NULL;
7629                 t->fogtexture = NULL;
7630                 t->reflectmasktexture = NULL;
7631                 t->backgroundbasetexture = NULL;
7632                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7633                 t->backgroundglosstexture = r_texture_black;
7634                 t->backgroundglowtexture = NULL;
7635                 t->specularscale = 0;
7636                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7637         }
7638
7639         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7640         VectorClear(t->dlightcolor);
7641         t->currentnumlayers = 0;
7642         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7643         {
7644                 int blendfunc1, blendfunc2;
7645                 qboolean depthmask;
7646                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7647                 {
7648                         blendfunc1 = GL_SRC_ALPHA;
7649                         blendfunc2 = GL_ONE;
7650                 }
7651                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7652                 {
7653                         blendfunc1 = GL_SRC_ALPHA;
7654                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7655                 }
7656                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7657                 {
7658                         blendfunc1 = t->customblendfunc[0];
7659                         blendfunc2 = t->customblendfunc[1];
7660                 }
7661                 else
7662                 {
7663                         blendfunc1 = GL_ONE;
7664                         blendfunc2 = GL_ZERO;
7665                 }
7666                 // don't colormod evilblend textures
7667                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7668                         VectorSet(t->lightmapcolor, 1, 1, 1);
7669                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7670                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7671                 {
7672                         // fullbright is not affected by r_refdef.lightmapintensity
7673                         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]);
7674                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7675                                 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]);
7676                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7677                                 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]);
7678                 }
7679                 else
7680                 {
7681                         vec3_t ambientcolor;
7682                         float colorscale;
7683                         // set the color tint used for lights affecting this surface
7684                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7685                         colorscale = 2;
7686                         // q3bsp has no lightmap updates, so the lightstylevalue that
7687                         // would normally be baked into the lightmap must be
7688                         // applied to the color
7689                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7690                         if (model->type == mod_brushq3)
7691                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7692                         colorscale *= r_refdef.lightmapintensity;
7693                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7694                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7695                         // basic lit geometry
7696                         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]);
7697                         // add pants/shirt if needed
7698                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7699                                 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]);
7700                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7701                                 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]);
7702                         // now add ambient passes if needed
7703                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7704                         {
7705                                 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]);
7706                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7707                                         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]);
7708                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7709                                         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]);
7710                         }
7711                 }
7712                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7713                         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]);
7714                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7715                 {
7716                         // if this is opaque use alpha blend which will darken the earlier
7717                         // passes cheaply.
7718                         //
7719                         // if this is an alpha blended material, all the earlier passes
7720                         // were darkened by fog already, so we only need to add the fog
7721                         // color ontop through the fog mask texture
7722                         //
7723                         // if this is an additive blended material, all the earlier passes
7724                         // were darkened by fog already, and we should not add fog color
7725                         // (because the background was not darkened, there is no fog color
7726                         // that was lost behind it).
7727                         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]);
7728                 }
7729         }
7730
7731         return t->currentframe;
7732 }
7733
7734 rsurfacestate_t rsurface;
7735
7736 void RSurf_ActiveWorldEntity(void)
7737 {
7738         dp_model_t *model = r_refdef.scene.worldmodel;
7739         //if (rsurface.entity == r_refdef.scene.worldentity)
7740         //      return;
7741         rsurface.entity = r_refdef.scene.worldentity;
7742         rsurface.skeleton = NULL;
7743         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7744         rsurface.ent_skinnum = 0;
7745         rsurface.ent_qwskin = -1;
7746         rsurface.ent_shadertime = 0;
7747         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7748         rsurface.matrix = identitymatrix;
7749         rsurface.inversematrix = identitymatrix;
7750         rsurface.matrixscale = 1;
7751         rsurface.inversematrixscale = 1;
7752         R_EntityMatrix(&identitymatrix);
7753         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7754         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7755         rsurface.fograngerecip = r_refdef.fograngerecip;
7756         rsurface.fogheightfade = r_refdef.fogheightfade;
7757         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7758         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7759         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7760         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7761         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7762         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7763         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7764         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7765         rsurface.colormod[3] = 1;
7766         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);
7767         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7768         rsurface.frameblend[0].lerp = 1;
7769         rsurface.ent_alttextures = false;
7770         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7771         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7772         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7773         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7774         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7775         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7776         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7777         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7778         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7779         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7780         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7781         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7782         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7783         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7784         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7785         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7786         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7787         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7788         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7789         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7790         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7791         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7792         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7793         rsurface.modelelement3i = model->surfmesh.data_element3i;
7794         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7795         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7796         rsurface.modelelement3s = model->surfmesh.data_element3s;
7797         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7798         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7799         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7800         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7801         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7802         rsurface.modelsurfaces = model->data_surfaces;
7803         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7804         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7805         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7806         rsurface.modelgeneratedvertex = false;
7807         rsurface.batchgeneratedvertex = false;
7808         rsurface.batchfirstvertex = 0;
7809         rsurface.batchnumvertices = 0;
7810         rsurface.batchfirsttriangle = 0;
7811         rsurface.batchnumtriangles = 0;
7812         rsurface.batchvertex3f  = NULL;
7813         rsurface.batchvertex3f_vertexbuffer = NULL;
7814         rsurface.batchvertex3f_bufferoffset = 0;
7815         rsurface.batchsvector3f = NULL;
7816         rsurface.batchsvector3f_vertexbuffer = NULL;
7817         rsurface.batchsvector3f_bufferoffset = 0;
7818         rsurface.batchtvector3f = NULL;
7819         rsurface.batchtvector3f_vertexbuffer = NULL;
7820         rsurface.batchtvector3f_bufferoffset = 0;
7821         rsurface.batchnormal3f  = NULL;
7822         rsurface.batchnormal3f_vertexbuffer = NULL;
7823         rsurface.batchnormal3f_bufferoffset = 0;
7824         rsurface.batchlightmapcolor4f = NULL;
7825         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7826         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7827         rsurface.batchtexcoordtexture2f = NULL;
7828         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7829         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7830         rsurface.batchtexcoordlightmap2f = NULL;
7831         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7832         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7833         rsurface.batchvertexmesh = NULL;
7834         rsurface.batchvertexmeshbuffer = NULL;
7835         rsurface.batchvertex3fbuffer = NULL;
7836         rsurface.batchelement3i = NULL;
7837         rsurface.batchelement3i_indexbuffer = NULL;
7838         rsurface.batchelement3i_bufferoffset = 0;
7839         rsurface.batchelement3s = NULL;
7840         rsurface.batchelement3s_indexbuffer = NULL;
7841         rsurface.batchelement3s_bufferoffset = 0;
7842         rsurface.passcolor4f = NULL;
7843         rsurface.passcolor4f_vertexbuffer = NULL;
7844         rsurface.passcolor4f_bufferoffset = 0;
7845 }
7846
7847 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7848 {
7849         dp_model_t *model = ent->model;
7850         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7851         //      return;
7852         rsurface.entity = (entity_render_t *)ent;
7853         rsurface.skeleton = ent->skeleton;
7854         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7855         rsurface.ent_skinnum = ent->skinnum;
7856         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;
7857         rsurface.ent_shadertime = ent->shadertime;
7858         rsurface.ent_flags = ent->flags;
7859         rsurface.matrix = ent->matrix;
7860         rsurface.inversematrix = ent->inversematrix;
7861         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7862         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7863         R_EntityMatrix(&rsurface.matrix);
7864         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7865         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7866         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7867         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7868         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7869         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7870         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7871         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7872         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7873         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7874         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7875         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7876         rsurface.colormod[3] = ent->alpha;
7877         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7878         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7879         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7880         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7881         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7882         if (ent->model->brush.submodel && !prepass)
7883         {
7884                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7885                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7886         }
7887         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7888         {
7889                 if (ent->animcache_vertex3f)
7890                 {
7891                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7892                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7893                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7894                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7895                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7896                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7897                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7898                 }
7899                 else if (wanttangents)
7900                 {
7901                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7902                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7903                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7904                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7905                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7906                         rsurface.modelvertexmesh = NULL;
7907                         rsurface.modelvertexmeshbuffer = NULL;
7908                         rsurface.modelvertex3fbuffer = NULL;
7909                 }
7910                 else if (wantnormals)
7911                 {
7912                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7913                         rsurface.modelsvector3f = NULL;
7914                         rsurface.modeltvector3f = NULL;
7915                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7916                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7917                         rsurface.modelvertexmesh = NULL;
7918                         rsurface.modelvertexmeshbuffer = NULL;
7919                         rsurface.modelvertex3fbuffer = NULL;
7920                 }
7921                 else
7922                 {
7923                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7924                         rsurface.modelsvector3f = NULL;
7925                         rsurface.modeltvector3f = NULL;
7926                         rsurface.modelnormal3f = NULL;
7927                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7928                         rsurface.modelvertexmesh = NULL;
7929                         rsurface.modelvertexmeshbuffer = NULL;
7930                         rsurface.modelvertex3fbuffer = NULL;
7931                 }
7932                 rsurface.modelvertex3f_vertexbuffer = 0;
7933                 rsurface.modelvertex3f_bufferoffset = 0;
7934                 rsurface.modelsvector3f_vertexbuffer = 0;
7935                 rsurface.modelsvector3f_bufferoffset = 0;
7936                 rsurface.modeltvector3f_vertexbuffer = 0;
7937                 rsurface.modeltvector3f_bufferoffset = 0;
7938                 rsurface.modelnormal3f_vertexbuffer = 0;
7939                 rsurface.modelnormal3f_bufferoffset = 0;
7940                 rsurface.modelgeneratedvertex = true;
7941         }
7942         else
7943         {
7944                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7945                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7946                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7947                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7948                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7949                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7950                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7951                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7952                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7953                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7954                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7955                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7956                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7957                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7958                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7959                 rsurface.modelgeneratedvertex = false;
7960         }
7961         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7962         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7963         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7964         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7965         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7966         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7967         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7968         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7969         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7970         rsurface.modelelement3i = model->surfmesh.data_element3i;
7971         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7972         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7973         rsurface.modelelement3s = model->surfmesh.data_element3s;
7974         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7975         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7976         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7977         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7978         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7979         rsurface.modelsurfaces = model->data_surfaces;
7980         rsurface.batchgeneratedvertex = false;
7981         rsurface.batchfirstvertex = 0;
7982         rsurface.batchnumvertices = 0;
7983         rsurface.batchfirsttriangle = 0;
7984         rsurface.batchnumtriangles = 0;
7985         rsurface.batchvertex3f  = NULL;
7986         rsurface.batchvertex3f_vertexbuffer = NULL;
7987         rsurface.batchvertex3f_bufferoffset = 0;
7988         rsurface.batchsvector3f = NULL;
7989         rsurface.batchsvector3f_vertexbuffer = NULL;
7990         rsurface.batchsvector3f_bufferoffset = 0;
7991         rsurface.batchtvector3f = NULL;
7992         rsurface.batchtvector3f_vertexbuffer = NULL;
7993         rsurface.batchtvector3f_bufferoffset = 0;
7994         rsurface.batchnormal3f  = NULL;
7995         rsurface.batchnormal3f_vertexbuffer = NULL;
7996         rsurface.batchnormal3f_bufferoffset = 0;
7997         rsurface.batchlightmapcolor4f = NULL;
7998         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7999         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8000         rsurface.batchtexcoordtexture2f = NULL;
8001         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8002         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8003         rsurface.batchtexcoordlightmap2f = NULL;
8004         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8005         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8006         rsurface.batchvertexmesh = NULL;
8007         rsurface.batchvertexmeshbuffer = NULL;
8008         rsurface.batchvertex3fbuffer = NULL;
8009         rsurface.batchelement3i = NULL;
8010         rsurface.batchelement3i_indexbuffer = NULL;
8011         rsurface.batchelement3i_bufferoffset = 0;
8012         rsurface.batchelement3s = NULL;
8013         rsurface.batchelement3s_indexbuffer = NULL;
8014         rsurface.batchelement3s_bufferoffset = 0;
8015         rsurface.passcolor4f = NULL;
8016         rsurface.passcolor4f_vertexbuffer = NULL;
8017         rsurface.passcolor4f_bufferoffset = 0;
8018 }
8019
8020 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)
8021 {
8022         rsurface.entity = r_refdef.scene.worldentity;
8023         rsurface.skeleton = NULL;
8024         rsurface.ent_skinnum = 0;
8025         rsurface.ent_qwskin = -1;
8026         rsurface.ent_shadertime = shadertime;
8027         rsurface.ent_flags = entflags;
8028         rsurface.modelnumvertices = numvertices;
8029         rsurface.modelnumtriangles = numtriangles;
8030         rsurface.matrix = *matrix;
8031         rsurface.inversematrix = *inversematrix;
8032         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8033         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8034         R_EntityMatrix(&rsurface.matrix);
8035         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8036         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8037         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8038         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8039         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8040         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8041         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8042         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8043         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8044         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8045         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8046         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8047         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);
8048         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8049         rsurface.frameblend[0].lerp = 1;
8050         rsurface.ent_alttextures = false;
8051         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8052         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8053         if (wanttangents)
8054         {
8055                 rsurface.modelvertex3f = (float *)vertex3f;
8056                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8057                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8058                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8059         }
8060         else if (wantnormals)
8061         {
8062                 rsurface.modelvertex3f = (float *)vertex3f;
8063                 rsurface.modelsvector3f = NULL;
8064                 rsurface.modeltvector3f = NULL;
8065                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8066         }
8067         else
8068         {
8069                 rsurface.modelvertex3f = (float *)vertex3f;
8070                 rsurface.modelsvector3f = NULL;
8071                 rsurface.modeltvector3f = NULL;
8072                 rsurface.modelnormal3f = NULL;
8073         }
8074         rsurface.modelvertexmesh = NULL;
8075         rsurface.modelvertexmeshbuffer = NULL;
8076         rsurface.modelvertex3fbuffer = NULL;
8077         rsurface.modelvertex3f_vertexbuffer = 0;
8078         rsurface.modelvertex3f_bufferoffset = 0;
8079         rsurface.modelsvector3f_vertexbuffer = 0;
8080         rsurface.modelsvector3f_bufferoffset = 0;
8081         rsurface.modeltvector3f_vertexbuffer = 0;
8082         rsurface.modeltvector3f_bufferoffset = 0;
8083         rsurface.modelnormal3f_vertexbuffer = 0;
8084         rsurface.modelnormal3f_bufferoffset = 0;
8085         rsurface.modelgeneratedvertex = true;
8086         rsurface.modellightmapcolor4f  = (float *)color4f;
8087         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8088         rsurface.modellightmapcolor4f_bufferoffset = 0;
8089         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8090         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8091         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8092         rsurface.modeltexcoordlightmap2f  = NULL;
8093         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8094         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8095         rsurface.modelelement3i = (int *)element3i;
8096         rsurface.modelelement3i_indexbuffer = NULL;
8097         rsurface.modelelement3i_bufferoffset = 0;
8098         rsurface.modelelement3s = (unsigned short *)element3s;
8099         rsurface.modelelement3s_indexbuffer = NULL;
8100         rsurface.modelelement3s_bufferoffset = 0;
8101         rsurface.modellightmapoffsets = NULL;
8102         rsurface.modelsurfaces = NULL;
8103         rsurface.batchgeneratedvertex = false;
8104         rsurface.batchfirstvertex = 0;
8105         rsurface.batchnumvertices = 0;
8106         rsurface.batchfirsttriangle = 0;
8107         rsurface.batchnumtriangles = 0;
8108         rsurface.batchvertex3f  = NULL;
8109         rsurface.batchvertex3f_vertexbuffer = NULL;
8110         rsurface.batchvertex3f_bufferoffset = 0;
8111         rsurface.batchsvector3f = NULL;
8112         rsurface.batchsvector3f_vertexbuffer = NULL;
8113         rsurface.batchsvector3f_bufferoffset = 0;
8114         rsurface.batchtvector3f = NULL;
8115         rsurface.batchtvector3f_vertexbuffer = NULL;
8116         rsurface.batchtvector3f_bufferoffset = 0;
8117         rsurface.batchnormal3f  = NULL;
8118         rsurface.batchnormal3f_vertexbuffer = NULL;
8119         rsurface.batchnormal3f_bufferoffset = 0;
8120         rsurface.batchlightmapcolor4f = NULL;
8121         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8122         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8123         rsurface.batchtexcoordtexture2f = NULL;
8124         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8125         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8126         rsurface.batchtexcoordlightmap2f = NULL;
8127         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8128         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8129         rsurface.batchvertexmesh = NULL;
8130         rsurface.batchvertexmeshbuffer = NULL;
8131         rsurface.batchvertex3fbuffer = NULL;
8132         rsurface.batchelement3i = NULL;
8133         rsurface.batchelement3i_indexbuffer = NULL;
8134         rsurface.batchelement3i_bufferoffset = 0;
8135         rsurface.batchelement3s = NULL;
8136         rsurface.batchelement3s_indexbuffer = NULL;
8137         rsurface.batchelement3s_bufferoffset = 0;
8138         rsurface.passcolor4f = NULL;
8139         rsurface.passcolor4f_vertexbuffer = NULL;
8140         rsurface.passcolor4f_bufferoffset = 0;
8141
8142         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8143         {
8144                 if ((wantnormals || wanttangents) && !normal3f)
8145                 {
8146                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8147                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8148                 }
8149                 if (wanttangents && !svector3f)
8150                 {
8151                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8152                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8153                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8154                 }
8155         }
8156 }
8157
8158 float RSurf_FogPoint(const float *v)
8159 {
8160         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8161         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8162         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8163         float FogHeightFade = r_refdef.fogheightfade;
8164         float fogfrac;
8165         unsigned int fogmasktableindex;
8166         if (r_refdef.fogplaneviewabove)
8167                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8168         else
8169                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8170         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8171         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8172 }
8173
8174 float RSurf_FogVertex(const float *v)
8175 {
8176         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8177         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8178         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8179         float FogHeightFade = rsurface.fogheightfade;
8180         float fogfrac;
8181         unsigned int fogmasktableindex;
8182         if (r_refdef.fogplaneviewabove)
8183                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8184         else
8185                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8186         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8187         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8188 }
8189
8190 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8191 {
8192         int i;
8193         for (i = 0;i < numelements;i++)
8194                 outelement3i[i] = inelement3i[i] + adjust;
8195 }
8196
8197 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8198 extern cvar_t gl_vbo;
8199 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8200 {
8201         int deformindex;
8202         int firsttriangle;
8203         int numtriangles;
8204         int firstvertex;
8205         int endvertex;
8206         int numvertices;
8207         int surfacefirsttriangle;
8208         int surfacenumtriangles;
8209         int surfacefirstvertex;
8210         int surfaceendvertex;
8211         int surfacenumvertices;
8212         int batchnumvertices;
8213         int batchnumtriangles;
8214         int needsupdate;
8215         int i, j;
8216         qboolean gaps;
8217         qboolean dynamicvertex;
8218         float amplitude;
8219         float animpos;
8220         float scale;
8221         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8222         float waveparms[4];
8223         q3shaderinfo_deform_t *deform;
8224         const msurface_t *surface, *firstsurface;
8225         r_vertexmesh_t *vertexmesh;
8226         if (!texturenumsurfaces)
8227                 return;
8228         // find vertex range of this surface batch
8229         gaps = false;
8230         firstsurface = texturesurfacelist[0];
8231         firsttriangle = firstsurface->num_firsttriangle;
8232         batchnumvertices = 0;
8233         batchnumtriangles = 0;
8234         firstvertex = endvertex = firstsurface->num_firstvertex;
8235         for (i = 0;i < texturenumsurfaces;i++)
8236         {
8237                 surface = texturesurfacelist[i];
8238                 if (surface != firstsurface + i)
8239                         gaps = true;
8240                 surfacefirstvertex = surface->num_firstvertex;
8241                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8242                 surfacenumvertices = surface->num_vertices;
8243                 surfacenumtriangles = surface->num_triangles;
8244                 if (firstvertex > surfacefirstvertex)
8245                         firstvertex = surfacefirstvertex;
8246                 if (endvertex < surfaceendvertex)
8247                         endvertex = surfaceendvertex;
8248                 batchnumvertices += surfacenumvertices;
8249                 batchnumtriangles += surfacenumtriangles;
8250         }
8251
8252         // we now know the vertex range used, and if there are any gaps in it
8253         rsurface.batchfirstvertex = firstvertex;
8254         rsurface.batchnumvertices = endvertex - firstvertex;
8255         rsurface.batchfirsttriangle = firsttriangle;
8256         rsurface.batchnumtriangles = batchnumtriangles;
8257
8258         // this variable holds flags for which properties have been updated that
8259         // may require regenerating vertexmesh array...
8260         needsupdate = 0;
8261
8262         // check if any dynamic vertex processing must occur
8263         dynamicvertex = false;
8264
8265         // if there is a chance of animated vertex colors, it's a dynamic batch
8266         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8267         {
8268                 dynamicvertex = true;
8269                 batchneed |= BATCHNEED_NOGAPS;
8270                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8271         }
8272
8273         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8274         {
8275                 switch (deform->deform)
8276                 {
8277                 default:
8278                 case Q3DEFORM_PROJECTIONSHADOW:
8279                 case Q3DEFORM_TEXT0:
8280                 case Q3DEFORM_TEXT1:
8281                 case Q3DEFORM_TEXT2:
8282                 case Q3DEFORM_TEXT3:
8283                 case Q3DEFORM_TEXT4:
8284                 case Q3DEFORM_TEXT5:
8285                 case Q3DEFORM_TEXT6:
8286                 case Q3DEFORM_TEXT7:
8287                 case Q3DEFORM_NONE:
8288                         break;
8289                 case Q3DEFORM_AUTOSPRITE:
8290                         dynamicvertex = true;
8291                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8292                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8293                         break;
8294                 case Q3DEFORM_AUTOSPRITE2:
8295                         dynamicvertex = true;
8296                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8297                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8298                         break;
8299                 case Q3DEFORM_NORMAL:
8300                         dynamicvertex = true;
8301                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8302                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8303                         break;
8304                 case Q3DEFORM_WAVE:
8305                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8306                                 break; // if wavefunc is a nop, ignore this transform
8307                         dynamicvertex = true;
8308                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8309                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8310                         break;
8311                 case Q3DEFORM_BULGE:
8312                         dynamicvertex = true;
8313                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8314                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8315                         break;
8316                 case Q3DEFORM_MOVE:
8317                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8318                                 break; // if wavefunc is a nop, ignore this transform
8319                         dynamicvertex = true;
8320                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8321                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8322                         break;
8323                 }
8324         }
8325         switch(rsurface.texture->tcgen.tcgen)
8326         {
8327         default:
8328         case Q3TCGEN_TEXTURE:
8329                 break;
8330         case Q3TCGEN_LIGHTMAP:
8331                 dynamicvertex = true;
8332                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8333                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8334                 break;
8335         case Q3TCGEN_VECTOR:
8336                 dynamicvertex = true;
8337                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8338                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8339                 break;
8340         case Q3TCGEN_ENVIRONMENT:
8341                 dynamicvertex = true;
8342                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8343                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8344                 break;
8345         }
8346         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8347         {
8348                 dynamicvertex = true;
8349                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8350                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8351         }
8352
8353         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8354         {
8355                 dynamicvertex = true;
8356                 batchneed |= BATCHNEED_NOGAPS;
8357                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8358         }
8359
8360         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8361         {
8362                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8363                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8364                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8365                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8366                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8367                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8368                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8369         }
8370
8371         // when the model data has no vertex buffer (dynamic mesh), we need to
8372         // eliminate gaps
8373         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8374                 batchneed |= BATCHNEED_NOGAPS;
8375
8376         // if needsupdate, we have to do a dynamic vertex batch for sure
8377         if (needsupdate & batchneed)
8378                 dynamicvertex = true;
8379
8380         // see if we need to build vertexmesh from arrays
8381         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8382                 dynamicvertex = true;
8383
8384         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8385         // also some drivers strongly dislike firstvertex
8386         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8387                 dynamicvertex = true;
8388
8389         rsurface.batchvertex3f = rsurface.modelvertex3f;
8390         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8391         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8392         rsurface.batchsvector3f = rsurface.modelsvector3f;
8393         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8394         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8395         rsurface.batchtvector3f = rsurface.modeltvector3f;
8396         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8397         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8398         rsurface.batchnormal3f = rsurface.modelnormal3f;
8399         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8400         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8401         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8402         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8403         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8404         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8405         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8406         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8407         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8408         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8409         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8410         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8411         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8412         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8413         rsurface.batchelement3i = rsurface.modelelement3i;
8414         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8415         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8416         rsurface.batchelement3s = rsurface.modelelement3s;
8417         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8418         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8419
8420         // if any dynamic vertex processing has to occur in software, we copy the
8421         // entire surface list together before processing to rebase the vertices
8422         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8423         //
8424         // if any gaps exist and we do not have a static vertex buffer, we have to
8425         // copy the surface list together to avoid wasting upload bandwidth on the
8426         // vertices in the gaps.
8427         //
8428         // if gaps exist and we have a static vertex buffer, we still have to
8429         // combine the index buffer ranges into one dynamic index buffer.
8430         //
8431         // in all cases we end up with data that can be drawn in one call.
8432
8433         if (!dynamicvertex)
8434         {
8435                 // static vertex data, just set pointers...
8436                 rsurface.batchgeneratedvertex = false;
8437                 // if there are gaps, we want to build a combined index buffer,
8438                 // otherwise use the original static buffer with an appropriate offset
8439                 if (gaps)
8440                 {
8441                         // build a new triangle elements array for this batch
8442                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8443                         rsurface.batchfirsttriangle = 0;
8444                         numtriangles = 0;
8445                         for (i = 0;i < texturenumsurfaces;i++)
8446                         {
8447                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8448                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8449                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8450                                 numtriangles += surfacenumtriangles;
8451                         }
8452                         rsurface.batchelement3i_indexbuffer = NULL;
8453                         rsurface.batchelement3i_bufferoffset = 0;
8454                         rsurface.batchelement3s = NULL;
8455                         rsurface.batchelement3s_indexbuffer = NULL;
8456                         rsurface.batchelement3s_bufferoffset = 0;
8457                         if (endvertex <= 65536)
8458                         {
8459                                 // make a 16bit (unsigned short) index array if possible
8460                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8461                                 for (i = 0;i < numtriangles*3;i++)
8462                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8463                         }
8464                 }
8465                 return;
8466         }
8467
8468         // something needs software processing, do it for real...
8469         // we only directly handle separate array data in this case and then
8470         // generate interleaved data if needed...
8471         rsurface.batchgeneratedvertex = true;
8472
8473         // now copy the vertex data into a combined array and make an index array
8474         // (this is what Quake3 does all the time)
8475         //if (gaps || rsurface.batchfirstvertex)
8476         {
8477                 rsurface.batchvertex3fbuffer = NULL;
8478                 rsurface.batchvertexmesh = NULL;
8479                 rsurface.batchvertexmeshbuffer = NULL;
8480                 rsurface.batchvertex3f = NULL;
8481                 rsurface.batchvertex3f_vertexbuffer = NULL;
8482                 rsurface.batchvertex3f_bufferoffset = 0;
8483                 rsurface.batchsvector3f = NULL;
8484                 rsurface.batchsvector3f_vertexbuffer = NULL;
8485                 rsurface.batchsvector3f_bufferoffset = 0;
8486                 rsurface.batchtvector3f = NULL;
8487                 rsurface.batchtvector3f_vertexbuffer = NULL;
8488                 rsurface.batchtvector3f_bufferoffset = 0;
8489                 rsurface.batchnormal3f = NULL;
8490                 rsurface.batchnormal3f_vertexbuffer = NULL;
8491                 rsurface.batchnormal3f_bufferoffset = 0;
8492                 rsurface.batchlightmapcolor4f = NULL;
8493                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8494                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8495                 rsurface.batchtexcoordtexture2f = NULL;
8496                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8497                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8498                 rsurface.batchtexcoordlightmap2f = NULL;
8499                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8500                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8501                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8502                 rsurface.batchelement3i_indexbuffer = NULL;
8503                 rsurface.batchelement3i_bufferoffset = 0;
8504                 rsurface.batchelement3s = NULL;
8505                 rsurface.batchelement3s_indexbuffer = NULL;
8506                 rsurface.batchelement3s_bufferoffset = 0;
8507                 // we'll only be setting up certain arrays as needed
8508                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8509                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8510                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8511                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8512                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8513                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8514                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8515                 {
8516                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8517                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8518                 }
8519                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8520                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8521                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8522                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8523                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8524                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8525                 numvertices = 0;
8526                 numtriangles = 0;
8527                 for (i = 0;i < texturenumsurfaces;i++)
8528                 {
8529                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8530                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8531                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8532                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8533                         // copy only the data requested
8534                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8535                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8536                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8537                         {
8538                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8539                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8540                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8541                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8542                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8543                                 {
8544                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8545                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8546                                 }
8547                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8548                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8549                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8550                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8551                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8552                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8553                         }
8554                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8555                         numvertices += surfacenumvertices;
8556                         numtriangles += surfacenumtriangles;
8557                 }
8558
8559                 // generate a 16bit index array as well if possible
8560                 // (in general, dynamic batches fit)
8561                 if (numvertices <= 65536)
8562                 {
8563                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8564                         for (i = 0;i < numtriangles*3;i++)
8565                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8566                 }
8567
8568                 // since we've copied everything, the batch now starts at 0
8569                 rsurface.batchfirstvertex = 0;
8570                 rsurface.batchnumvertices = batchnumvertices;
8571                 rsurface.batchfirsttriangle = 0;
8572                 rsurface.batchnumtriangles = batchnumtriangles;
8573         }
8574
8575         // q1bsp surfaces rendered in vertex color mode have to have colors
8576         // calculated based on lightstyles
8577         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8578         {
8579                 // generate color arrays for the surfaces in this list
8580                 int c[4];
8581                 int scale;
8582                 int size3;
8583                 const int *offsets;
8584                 const unsigned char *lm;
8585                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8586                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8587                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8588                 numvertices = 0;
8589                 for (i = 0;i < texturenumsurfaces;i++)
8590                 {
8591                         surface = texturesurfacelist[i];
8592                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8593                         surfacenumvertices = surface->num_vertices;
8594                         if (surface->lightmapinfo->samples)
8595                         {
8596                                 for (j = 0;j < surfacenumvertices;j++)
8597                                 {
8598                                         lm = surface->lightmapinfo->samples + offsets[j];
8599                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8600                                         VectorScale(lm, scale, c);
8601                                         if (surface->lightmapinfo->styles[1] != 255)
8602                                         {
8603                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8604                                                 lm += size3;
8605                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8606                                                 VectorMA(c, scale, lm, c);
8607                                                 if (surface->lightmapinfo->styles[2] != 255)
8608                                                 {
8609                                                         lm += size3;
8610                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8611                                                         VectorMA(c, scale, lm, c);
8612                                                         if (surface->lightmapinfo->styles[3] != 255)
8613                                                         {
8614                                                                 lm += size3;
8615                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8616                                                                 VectorMA(c, scale, lm, c);
8617                                                         }
8618                                                 }
8619                                         }
8620                                         c[0] >>= 7;
8621                                         c[1] >>= 7;
8622                                         c[2] >>= 7;
8623                                         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);
8624                                         numvertices++;
8625                                 }
8626                         }
8627                         else
8628                         {
8629                                 for (j = 0;j < surfacenumvertices;j++)
8630                                 {
8631                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8632                                         numvertices++;
8633                                 }
8634                         }
8635                 }
8636         }
8637
8638         // if vertices are deformed (sprite flares and things in maps, possibly
8639         // water waves, bulges and other deformations), modify the copied vertices
8640         // in place
8641         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8642         {
8643                 switch (deform->deform)
8644                 {
8645                 default:
8646                 case Q3DEFORM_PROJECTIONSHADOW:
8647                 case Q3DEFORM_TEXT0:
8648                 case Q3DEFORM_TEXT1:
8649                 case Q3DEFORM_TEXT2:
8650                 case Q3DEFORM_TEXT3:
8651                 case Q3DEFORM_TEXT4:
8652                 case Q3DEFORM_TEXT5:
8653                 case Q3DEFORM_TEXT6:
8654                 case Q3DEFORM_TEXT7:
8655                 case Q3DEFORM_NONE:
8656                         break;
8657                 case Q3DEFORM_AUTOSPRITE:
8658                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8659                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8660                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8661                         VectorNormalize(newforward);
8662                         VectorNormalize(newright);
8663                         VectorNormalize(newup);
8664 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8665 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8666 //                      rsurface.batchvertex3f_bufferoffset = 0;
8667 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8668 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8669 //                      rsurface.batchsvector3f_bufferoffset = 0;
8670 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8671 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8672 //                      rsurface.batchtvector3f_bufferoffset = 0;
8673 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8674 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8675 //                      rsurface.batchnormal3f_bufferoffset = 0;
8676                         // a single autosprite surface can contain multiple sprites...
8677                         for (j = 0;j < batchnumvertices - 3;j += 4)
8678                         {
8679                                 VectorClear(center);
8680                                 for (i = 0;i < 4;i++)
8681                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8682                                 VectorScale(center, 0.25f, center);
8683                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8684                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8685                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8686                                 for (i = 0;i < 4;i++)
8687                                 {
8688                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8689                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8690                                 }
8691                         }
8692                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8693                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8694                         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);
8695                         break;
8696                 case Q3DEFORM_AUTOSPRITE2:
8697                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8698                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8699                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8700                         VectorNormalize(newforward);
8701                         VectorNormalize(newright);
8702                         VectorNormalize(newup);
8703 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8704 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8705 //                      rsurface.batchvertex3f_bufferoffset = 0;
8706                         {
8707                                 const float *v1, *v2;
8708                                 vec3_t start, end;
8709                                 float f, l;
8710                                 struct
8711                                 {
8712                                         float length2;
8713                                         const float *v1;
8714                                         const float *v2;
8715                                 }
8716                                 shortest[2];
8717                                 memset(shortest, 0, sizeof(shortest));
8718                                 // a single autosprite surface can contain multiple sprites...
8719                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8720                                 {
8721                                         VectorClear(center);
8722                                         for (i = 0;i < 4;i++)
8723                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8724                                         VectorScale(center, 0.25f, center);
8725                                         // find the two shortest edges, then use them to define the
8726                                         // axis vectors for rotating around the central axis
8727                                         for (i = 0;i < 6;i++)
8728                                         {
8729                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8730                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8731                                                 l = VectorDistance2(v1, v2);
8732                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8733                                                 if (v1[2] != v2[2])
8734                                                         l += (1.0f / 1024.0f);
8735                                                 if (shortest[0].length2 > l || i == 0)
8736                                                 {
8737                                                         shortest[1] = shortest[0];
8738                                                         shortest[0].length2 = l;
8739                                                         shortest[0].v1 = v1;
8740                                                         shortest[0].v2 = v2;
8741                                                 }
8742                                                 else if (shortest[1].length2 > l || i == 1)
8743                                                 {
8744                                                         shortest[1].length2 = l;
8745                                                         shortest[1].v1 = v1;
8746                                                         shortest[1].v2 = v2;
8747                                                 }
8748                                         }
8749                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8750                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8751                                         // this calculates the right vector from the shortest edge
8752                                         // and the up vector from the edge midpoints
8753                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8754                                         VectorNormalize(right);
8755                                         VectorSubtract(end, start, up);
8756                                         VectorNormalize(up);
8757                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8758                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8759                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8760                                         VectorNegate(forward, forward);
8761                                         VectorReflect(forward, 0, up, forward);
8762                                         VectorNormalize(forward);
8763                                         CrossProduct(up, forward, newright);
8764                                         VectorNormalize(newright);
8765                                         // rotate the quad around the up axis vector, this is made
8766                                         // especially easy by the fact we know the quad is flat,
8767                                         // so we only have to subtract the center position and
8768                                         // measure distance along the right vector, and then
8769                                         // multiply that by the newright vector and add back the
8770                                         // center position
8771                                         // we also need to subtract the old position to undo the
8772                                         // displacement from the center, which we do with a
8773                                         // DotProduct, the subtraction/addition of center is also
8774                                         // optimized into DotProducts here
8775                                         l = DotProduct(right, center);
8776                                         for (i = 0;i < 4;i++)
8777                                         {
8778                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8779                                                 f = DotProduct(right, v1) - l;
8780                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8781                                         }
8782                                 }
8783                         }
8784                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8785                         {
8786 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8787 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8788 //                              rsurface.batchnormal3f_bufferoffset = 0;
8789                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8790                         }
8791                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8792                         {
8793 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8794 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8795 //                              rsurface.batchsvector3f_bufferoffset = 0;
8796 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8797 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8798 //                              rsurface.batchtvector3f_bufferoffset = 0;
8799                                 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);
8800                         }
8801                         break;
8802                 case Q3DEFORM_NORMAL:
8803                         // deform the normals to make reflections wavey
8804                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8805                         rsurface.batchnormal3f_vertexbuffer = NULL;
8806                         rsurface.batchnormal3f_bufferoffset = 0;
8807                         for (j = 0;j < batchnumvertices;j++)
8808                         {
8809                                 float vertex[3];
8810                                 float *normal = rsurface.batchnormal3f + 3*j;
8811                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8812                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8813                                 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]);
8814                                 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]);
8815                                 VectorNormalize(normal);
8816                         }
8817                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8818                         {
8819 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8820 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8821 //                              rsurface.batchsvector3f_bufferoffset = 0;
8822 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8823 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8824 //                              rsurface.batchtvector3f_bufferoffset = 0;
8825                                 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);
8826                         }
8827                         break;
8828                 case Q3DEFORM_WAVE:
8829                         // deform vertex array to make wavey water and flags and such
8830                         waveparms[0] = deform->waveparms[0];
8831                         waveparms[1] = deform->waveparms[1];
8832                         waveparms[2] = deform->waveparms[2];
8833                         waveparms[3] = deform->waveparms[3];
8834                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8835                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8836                         // this is how a divisor of vertex influence on deformation
8837                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8838                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8839 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8840 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8841 //                      rsurface.batchvertex3f_bufferoffset = 0;
8842 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8843 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8844 //                      rsurface.batchnormal3f_bufferoffset = 0;
8845                         for (j = 0;j < batchnumvertices;j++)
8846                         {
8847                                 // if the wavefunc depends on time, evaluate it per-vertex
8848                                 if (waveparms[3])
8849                                 {
8850                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8851                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8852                                 }
8853                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8854                         }
8855                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8856                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8857                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8858                         {
8859 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8860 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8861 //                              rsurface.batchsvector3f_bufferoffset = 0;
8862 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8863 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8864 //                              rsurface.batchtvector3f_bufferoffset = 0;
8865                                 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);
8866                         }
8867                         break;
8868                 case Q3DEFORM_BULGE:
8869                         // deform vertex array to make the surface have moving bulges
8870 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8871 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8872 //                      rsurface.batchvertex3f_bufferoffset = 0;
8873 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8874 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8875 //                      rsurface.batchnormal3f_bufferoffset = 0;
8876                         for (j = 0;j < batchnumvertices;j++)
8877                         {
8878                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8879                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8880                         }
8881                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8882                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8883                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8884                         {
8885 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8886 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8887 //                              rsurface.batchsvector3f_bufferoffset = 0;
8888 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8889 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8890 //                              rsurface.batchtvector3f_bufferoffset = 0;
8891                                 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);
8892                         }
8893                         break;
8894                 case Q3DEFORM_MOVE:
8895                         // deform vertex array
8896                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8897                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8898                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8899                         VectorScale(deform->parms, scale, waveparms);
8900 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8901 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8902 //                      rsurface.batchvertex3f_bufferoffset = 0;
8903                         for (j = 0;j < batchnumvertices;j++)
8904                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8905                         break;
8906                 }
8907         }
8908
8909         // generate texcoords based on the chosen texcoord source
8910         switch(rsurface.texture->tcgen.tcgen)
8911         {
8912         default:
8913         case Q3TCGEN_TEXTURE:
8914                 break;
8915         case Q3TCGEN_LIGHTMAP:
8916 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8917 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8918 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8919                 if (rsurface.batchtexcoordlightmap2f)
8920                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8921                 break;
8922         case Q3TCGEN_VECTOR:
8923 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8924 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8925 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8926                 for (j = 0;j < batchnumvertices;j++)
8927                 {
8928                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8929                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8930                 }
8931                 break;
8932         case Q3TCGEN_ENVIRONMENT:
8933                 // make environment reflections using a spheremap
8934                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8935                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8936                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8937                 for (j = 0;j < batchnumvertices;j++)
8938                 {
8939                         // identical to Q3A's method, but executed in worldspace so
8940                         // carried models can be shiny too
8941
8942                         float viewer[3], d, reflected[3], worldreflected[3];
8943
8944                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8945                         // VectorNormalize(viewer);
8946
8947                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8948
8949                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8950                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8951                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8952                         // note: this is proportinal to viewer, so we can normalize later
8953
8954                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8955                         VectorNormalize(worldreflected);
8956
8957                         // note: this sphere map only uses world x and z!
8958                         // so positive and negative y will LOOK THE SAME.
8959                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8960                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8961                 }
8962                 break;
8963         }
8964         // the only tcmod that needs software vertex processing is turbulent, so
8965         // check for it here and apply the changes if needed
8966         // and we only support that as the first one
8967         // (handling a mixture of turbulent and other tcmods would be problematic
8968         //  without punting it entirely to a software path)
8969         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8970         {
8971                 amplitude = rsurface.texture->tcmods[0].parms[1];
8972                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8973 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8974 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8975 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8976                 for (j = 0;j < batchnumvertices;j++)
8977                 {
8978                         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);
8979                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8980                 }
8981         }
8982
8983         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8984         {
8985                 // convert the modified arrays to vertex structs
8986 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8987 //              rsurface.batchvertexmeshbuffer = NULL;
8988                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8989                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8990                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8991                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8992                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8993                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8994                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8995                 {
8996                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8997                         {
8998                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8999                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9000                         }
9001                 }
9002                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9003                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9004                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9005                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9006                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9007                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9008                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9009                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9010                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9011         }
9012 }
9013
9014 void RSurf_DrawBatch(void)
9015 {
9016         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9017         // through the pipeline, killing it earlier in the pipeline would have
9018         // per-surface overhead rather than per-batch overhead, so it's best to
9019         // reject it here, before it hits glDraw.
9020         if (rsurface.batchnumtriangles == 0)
9021                 return;
9022 #if 0
9023         // batch debugging code
9024         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9025         {
9026                 int i;
9027                 int j;
9028                 int c;
9029                 const int *e;
9030                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9031                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9032                 {
9033                         c = e[i];
9034                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9035                         {
9036                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9037                                 {
9038                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9039                                                 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);
9040                                         break;
9041                                 }
9042                         }
9043                 }
9044         }
9045 #endif
9046         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);
9047 }
9048
9049 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9050 {
9051         // pick the closest matching water plane
9052         int planeindex, vertexindex, bestplaneindex = -1;
9053         float d, bestd;
9054         vec3_t vert;
9055         const float *v;
9056         r_waterstate_waterplane_t *p;
9057         qboolean prepared = false;
9058         bestd = 0;
9059         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9060         {
9061                 if(p->camera_entity != rsurface.texture->camera_entity)
9062                         continue;
9063                 d = 0;
9064                 if(!prepared)
9065                 {
9066                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9067                         prepared = true;
9068                         if(rsurface.batchnumvertices == 0)
9069                                 break;
9070                 }
9071                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9072                 {
9073                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9074                         d += fabs(PlaneDiff(vert, &p->plane));
9075                 }
9076                 if (bestd > d || bestplaneindex < 0)
9077                 {
9078                         bestd = d;
9079                         bestplaneindex = planeindex;
9080                 }
9081         }
9082         return bestplaneindex;
9083         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9084         // this situation though, as it might be better to render single larger
9085         // batches with useless stuff (backface culled for example) than to
9086         // render multiple smaller batches
9087 }
9088
9089 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9090 {
9091         int i;
9092         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9093         rsurface.passcolor4f_vertexbuffer = 0;
9094         rsurface.passcolor4f_bufferoffset = 0;
9095         for (i = 0;i < rsurface.batchnumvertices;i++)
9096                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9097 }
9098
9099 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9100 {
9101         int i;
9102         float f;
9103         const float *v;
9104         const float *c;
9105         float *c2;
9106         if (rsurface.passcolor4f)
9107         {
9108                 // generate color arrays
9109                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9110                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9111                 rsurface.passcolor4f_vertexbuffer = 0;
9112                 rsurface.passcolor4f_bufferoffset = 0;
9113                 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)
9114                 {
9115                         f = RSurf_FogVertex(v);
9116                         c2[0] = c[0] * f;
9117                         c2[1] = c[1] * f;
9118                         c2[2] = c[2] * f;
9119                         c2[3] = c[3];
9120                 }
9121         }
9122         else
9123         {
9124                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9125                 rsurface.passcolor4f_vertexbuffer = 0;
9126                 rsurface.passcolor4f_bufferoffset = 0;
9127                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9128                 {
9129                         f = RSurf_FogVertex(v);
9130                         c2[0] = f;
9131                         c2[1] = f;
9132                         c2[2] = f;
9133                         c2[3] = 1;
9134                 }
9135         }
9136 }
9137
9138 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9139 {
9140         int i;
9141         float f;
9142         const float *v;
9143         const float *c;
9144         float *c2;
9145         if (!rsurface.passcolor4f)
9146                 return;
9147         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9148         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9149         rsurface.passcolor4f_vertexbuffer = 0;
9150         rsurface.passcolor4f_bufferoffset = 0;
9151         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9152         {
9153                 f = RSurf_FogVertex(v);
9154                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9155                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9156                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9157                 c2[3] = c[3];
9158         }
9159 }
9160
9161 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9162 {
9163         int i;
9164         const float *c;
9165         float *c2;
9166         if (!rsurface.passcolor4f)
9167                 return;
9168         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9169         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9170         rsurface.passcolor4f_vertexbuffer = 0;
9171         rsurface.passcolor4f_bufferoffset = 0;
9172         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9173         {
9174                 c2[0] = c[0] * r;
9175                 c2[1] = c[1] * g;
9176                 c2[2] = c[2] * b;
9177                 c2[3] = c[3] * a;
9178         }
9179 }
9180
9181 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9182 {
9183         int i;
9184         const float *c;
9185         float *c2;
9186         if (!rsurface.passcolor4f)
9187                 return;
9188         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9189         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9190         rsurface.passcolor4f_vertexbuffer = 0;
9191         rsurface.passcolor4f_bufferoffset = 0;
9192         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9193         {
9194                 c2[0] = c[0] + r_refdef.scene.ambient;
9195                 c2[1] = c[1] + r_refdef.scene.ambient;
9196                 c2[2] = c[2] + r_refdef.scene.ambient;
9197                 c2[3] = c[3];
9198         }
9199 }
9200
9201 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9202 {
9203         // TODO: optimize
9204         rsurface.passcolor4f = NULL;
9205         rsurface.passcolor4f_vertexbuffer = 0;
9206         rsurface.passcolor4f_bufferoffset = 0;
9207         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9208         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9209         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9210         GL_Color(r, g, b, a);
9211         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9212         RSurf_DrawBatch();
9213 }
9214
9215 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9216 {
9217         // TODO: optimize applyfog && applycolor case
9218         // just apply fog if necessary, and tint the fog color array if necessary
9219         rsurface.passcolor4f = NULL;
9220         rsurface.passcolor4f_vertexbuffer = 0;
9221         rsurface.passcolor4f_bufferoffset = 0;
9222         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9223         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9224         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9225         GL_Color(r, g, b, a);
9226         RSurf_DrawBatch();
9227 }
9228
9229 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9230 {
9231         // TODO: optimize
9232         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9233         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9234         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9235         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9236         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9237         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9238         GL_Color(r, g, b, a);
9239         RSurf_DrawBatch();
9240 }
9241
9242 static void RSurf_DrawBatch_GL11_ClampColor(void)
9243 {
9244         int i;
9245         const float *c1;
9246         float *c2;
9247         if (!rsurface.passcolor4f)
9248                 return;
9249         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9250         {
9251                 c2[0] = bound(0.0f, c1[0], 1.0f);
9252                 c2[1] = bound(0.0f, c1[1], 1.0f);
9253                 c2[2] = bound(0.0f, c1[2], 1.0f);
9254                 c2[3] = bound(0.0f, c1[3], 1.0f);
9255         }
9256 }
9257
9258 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9259 {
9260         int i;
9261         float f;
9262         const float *v;
9263         const float *n;
9264         float *c;
9265         //vec3_t eyedir;
9266
9267         // fake shading
9268         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9269         rsurface.passcolor4f_vertexbuffer = 0;
9270         rsurface.passcolor4f_bufferoffset = 0;
9271         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)
9272         {
9273                 f = -DotProduct(r_refdef.view.forward, n);
9274                 f = max(0, f);
9275                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9276                 f *= r_refdef.lightmapintensity;
9277                 Vector4Set(c, f, f, f, 1);
9278         }
9279 }
9280
9281 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9282 {
9283         RSurf_DrawBatch_GL11_ApplyFakeLight();
9284         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9285         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9286         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9287         GL_Color(r, g, b, a);
9288         RSurf_DrawBatch();
9289 }
9290
9291 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9292 {
9293         int i;
9294         float f;
9295         float alpha;
9296         const float *v;
9297         const float *n;
9298         float *c;
9299         vec3_t ambientcolor;
9300         vec3_t diffusecolor;
9301         vec3_t lightdir;
9302         // TODO: optimize
9303         // model lighting
9304         VectorCopy(rsurface.modellight_lightdir, lightdir);
9305         f = 0.5f * r_refdef.lightmapintensity;
9306         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9307         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9308         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9309         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9310         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9311         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9312         alpha = *a;
9313         if (VectorLength2(diffusecolor) > 0)
9314         {
9315                 // q3-style directional shading
9316                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9317                 rsurface.passcolor4f_vertexbuffer = 0;
9318                 rsurface.passcolor4f_bufferoffset = 0;
9319                 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)
9320                 {
9321                         if ((f = DotProduct(n, lightdir)) > 0)
9322                                 VectorMA(ambientcolor, f, diffusecolor, c);
9323                         else
9324                                 VectorCopy(ambientcolor, c);
9325                         c[3] = alpha;
9326                 }
9327                 *r = 1;
9328                 *g = 1;
9329                 *b = 1;
9330                 *a = 1;
9331                 *applycolor = false;
9332         }
9333         else
9334         {
9335                 *r = ambientcolor[0];
9336                 *g = ambientcolor[1];
9337                 *b = ambientcolor[2];
9338                 rsurface.passcolor4f = NULL;
9339                 rsurface.passcolor4f_vertexbuffer = 0;
9340                 rsurface.passcolor4f_bufferoffset = 0;
9341         }
9342 }
9343
9344 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9345 {
9346         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9347         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9348         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9349         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9350         GL_Color(r, g, b, a);
9351         RSurf_DrawBatch();
9352 }
9353
9354 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9355 {
9356         int i;
9357         float f;
9358         const float *v;
9359         float *c;
9360
9361         // fake shading
9362         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9363         rsurface.passcolor4f_vertexbuffer = 0;
9364         rsurface.passcolor4f_bufferoffset = 0;
9365
9366         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9367         {
9368                 f = 1 - RSurf_FogVertex(v);
9369                 c[0] = r;
9370                 c[1] = g;
9371                 c[2] = b;
9372                 c[3] = f * a;
9373         }
9374 }
9375
9376 void RSurf_SetupDepthAndCulling(void)
9377 {
9378         // submodels are biased to avoid z-fighting with world surfaces that they
9379         // may be exactly overlapping (avoids z-fighting artifacts on certain
9380         // doors and things in Quake maps)
9381         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9382         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9383         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9384         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9385 }
9386
9387 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9388 {
9389         // transparent sky would be ridiculous
9390         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9391                 return;
9392         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9393         skyrenderlater = true;
9394         RSurf_SetupDepthAndCulling();
9395         GL_DepthMask(true);
9396         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9397         // skymasking on them, and Quake3 never did sky masking (unlike
9398         // software Quake and software Quake2), so disable the sky masking
9399         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9400         // and skymasking also looks very bad when noclipping outside the
9401         // level, so don't use it then either.
9402         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9403         {
9404                 R_Mesh_ResetTextureState();
9405                 if (skyrendermasked)
9406                 {
9407                         R_SetupShader_DepthOrShadow();
9408                         // depth-only (masking)
9409                         GL_ColorMask(0,0,0,0);
9410                         // just to make sure that braindead drivers don't draw
9411                         // anything despite that colormask...
9412                         GL_BlendFunc(GL_ZERO, GL_ONE);
9413                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9414                         if (rsurface.batchvertex3fbuffer)
9415                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9416                         else
9417                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9418                 }
9419                 else
9420                 {
9421                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9422                         // fog sky
9423                         GL_BlendFunc(GL_ONE, GL_ZERO);
9424                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9425                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9426                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9427                 }
9428                 RSurf_DrawBatch();
9429                 if (skyrendermasked)
9430                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9431         }
9432         R_Mesh_ResetTextureState();
9433         GL_Color(1, 1, 1, 1);
9434 }
9435
9436 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9437 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9438 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9439 {
9440         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9441                 return;
9442         if (prepass)
9443         {
9444                 // render screenspace normalmap to texture
9445                 GL_DepthMask(true);
9446                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9447                 RSurf_DrawBatch();
9448                 return;
9449         }
9450
9451         // bind lightmap texture
9452
9453         // water/refraction/reflection/camera surfaces have to be handled specially
9454         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9455         {
9456                 int start, end, startplaneindex;
9457                 for (start = 0;start < texturenumsurfaces;start = end)
9458                 {
9459                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9460                         if(startplaneindex < 0)
9461                         {
9462                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9463                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9464                                 end = start + 1;
9465                                 continue;
9466                         }
9467                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9468                                 ;
9469                         // now that we have a batch using the same planeindex, render it
9470                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9471                         {
9472                                 // render water or distortion background
9473                                 GL_DepthMask(true);
9474                                 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));
9475                                 RSurf_DrawBatch();
9476                                 // blend surface on top
9477                                 GL_DepthMask(false);
9478                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9479                                 RSurf_DrawBatch();
9480                         }
9481                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9482                         {
9483                                 // render surface with reflection texture as input
9484                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9485                                 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));
9486                                 RSurf_DrawBatch();
9487                         }
9488                 }
9489                 return;
9490         }
9491
9492         // render surface batch normally
9493         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9494         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9495         RSurf_DrawBatch();
9496 }
9497
9498 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9499 {
9500         // OpenGL 1.3 path - anything not completely ancient
9501         qboolean applycolor;
9502         qboolean applyfog;
9503         int layerindex;
9504         const texturelayer_t *layer;
9505         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);
9506         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9507
9508         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9509         {
9510                 vec4_t layercolor;
9511                 int layertexrgbscale;
9512                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9513                 {
9514                         if (layerindex == 0)
9515                                 GL_AlphaTest(true);
9516                         else
9517                         {
9518                                 GL_AlphaTest(false);
9519                                 GL_DepthFunc(GL_EQUAL);
9520                         }
9521                 }
9522                 GL_DepthMask(layer->depthmask && writedepth);
9523                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9524                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9525                 {
9526                         layertexrgbscale = 4;
9527                         VectorScale(layer->color, 0.25f, layercolor);
9528                 }
9529                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9530                 {
9531                         layertexrgbscale = 2;
9532                         VectorScale(layer->color, 0.5f, layercolor);
9533                 }
9534                 else
9535                 {
9536                         layertexrgbscale = 1;
9537                         VectorScale(layer->color, 1.0f, layercolor);
9538                 }
9539                 layercolor[3] = layer->color[3];
9540                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9541                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9542                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9543                 switch (layer->type)
9544                 {
9545                 case TEXTURELAYERTYPE_LITTEXTURE:
9546                         // single-pass lightmapped texture with 2x rgbscale
9547                         R_Mesh_TexBind(0, r_texture_white);
9548                         R_Mesh_TexMatrix(0, NULL);
9549                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9550                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9551                         R_Mesh_TexBind(1, layer->texture);
9552                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9553                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9554                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9555                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9556                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9557                         else if (FAKELIGHT_ENABLED)
9558                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9559                         else if (rsurface.uselightmaptexture)
9560                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9561                         else
9562                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9563                         break;
9564                 case TEXTURELAYERTYPE_TEXTURE:
9565                         // singletexture unlit texture with transparency support
9566                         R_Mesh_TexBind(0, layer->texture);
9567                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9568                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9569                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9570                         R_Mesh_TexBind(1, 0);
9571                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9572                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9573                         break;
9574                 case TEXTURELAYERTYPE_FOG:
9575                         // singletexture fogging
9576                         if (layer->texture)
9577                         {
9578                                 R_Mesh_TexBind(0, layer->texture);
9579                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9580                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9581                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9582                         }
9583                         else
9584                         {
9585                                 R_Mesh_TexBind(0, 0);
9586                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9587                         }
9588                         R_Mesh_TexBind(1, 0);
9589                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9590                         // generate a color array for the fog pass
9591                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9592                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9593                         RSurf_DrawBatch();
9594                         break;
9595                 default:
9596                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9597                 }
9598         }
9599         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9600         {
9601                 GL_DepthFunc(GL_LEQUAL);
9602                 GL_AlphaTest(false);
9603         }
9604 }
9605
9606 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9607 {
9608         // OpenGL 1.1 - crusty old voodoo path
9609         qboolean applyfog;
9610         int layerindex;
9611         const texturelayer_t *layer;
9612         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);
9613         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9614
9615         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9616         {
9617                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9618                 {
9619                         if (layerindex == 0)
9620                                 GL_AlphaTest(true);
9621                         else
9622                         {
9623                                 GL_AlphaTest(false);
9624                                 GL_DepthFunc(GL_EQUAL);
9625                         }
9626                 }
9627                 GL_DepthMask(layer->depthmask && writedepth);
9628                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9629                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9630                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9631                 switch (layer->type)
9632                 {
9633                 case TEXTURELAYERTYPE_LITTEXTURE:
9634                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9635                         {
9636                                 // two-pass lit texture with 2x rgbscale
9637                                 // first the lightmap pass
9638                                 R_Mesh_TexBind(0, r_texture_white);
9639                                 R_Mesh_TexMatrix(0, NULL);
9640                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9641                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9642                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9643                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9644                                 else if (FAKELIGHT_ENABLED)
9645                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9646                                 else if (rsurface.uselightmaptexture)
9647                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9648                                 else
9649                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9650                                 // then apply the texture to it
9651                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9652                                 R_Mesh_TexBind(0, layer->texture);
9653                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9654                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9655                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9656                                 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);
9657                         }
9658                         else
9659                         {
9660                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9661                                 R_Mesh_TexBind(0, layer->texture);
9662                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9663                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9664                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9665                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9666                                         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);
9667                                 else
9668                                         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);
9669                         }
9670                         break;
9671                 case TEXTURELAYERTYPE_TEXTURE:
9672                         // singletexture unlit texture with transparency support
9673                         R_Mesh_TexBind(0, layer->texture);
9674                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9675                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9676                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9677                         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);
9678                         break;
9679                 case TEXTURELAYERTYPE_FOG:
9680                         // singletexture fogging
9681                         if (layer->texture)
9682                         {
9683                                 R_Mesh_TexBind(0, layer->texture);
9684                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9685                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9686                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9687                         }
9688                         else
9689                         {
9690                                 R_Mesh_TexBind(0, 0);
9691                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9692                         }
9693                         // generate a color array for the fog pass
9694                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9695                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9696                         RSurf_DrawBatch();
9697                         break;
9698                 default:
9699                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9700                 }
9701         }
9702         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9703         {
9704                 GL_DepthFunc(GL_LEQUAL);
9705                 GL_AlphaTest(false);
9706         }
9707 }
9708
9709 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9710 {
9711         int vi;
9712         int j;
9713         r_vertexgeneric_t *batchvertex;
9714         float c[4];
9715
9716 //      R_Mesh_ResetTextureState();
9717         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9718
9719         if(rsurface.texture && rsurface.texture->currentskinframe)
9720         {
9721                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9722                 c[3] *= rsurface.texture->currentalpha;
9723         }
9724         else
9725         {
9726                 c[0] = 1;
9727                 c[1] = 0;
9728                 c[2] = 1;
9729                 c[3] = 1;
9730         }
9731
9732         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9733         {
9734                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9735                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9736                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9737         }
9738
9739         // brighten it up (as texture value 127 means "unlit")
9740         c[0] *= 2 * r_refdef.view.colorscale;
9741         c[1] *= 2 * r_refdef.view.colorscale;
9742         c[2] *= 2 * r_refdef.view.colorscale;
9743
9744         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9745                 c[3] *= r_wateralpha.value;
9746
9747         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9748         {
9749                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9750                 GL_DepthMask(false);
9751         }
9752         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9753         {
9754                 GL_BlendFunc(GL_ONE, GL_ONE);
9755                 GL_DepthMask(false);
9756         }
9757         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9758         {
9759                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9760                 GL_DepthMask(false);
9761         }
9762         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9763         {
9764                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9765                 GL_DepthMask(false);
9766         }
9767         else
9768         {
9769                 GL_BlendFunc(GL_ONE, GL_ZERO);
9770                 GL_DepthMask(writedepth);
9771         }
9772
9773         if (r_showsurfaces.integer == 3)
9774         {
9775                 rsurface.passcolor4f = NULL;
9776
9777                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9778                 {
9779                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9780
9781                         rsurface.passcolor4f = NULL;
9782                         rsurface.passcolor4f_vertexbuffer = 0;
9783                         rsurface.passcolor4f_bufferoffset = 0;
9784                 }
9785                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9786                 {
9787                         qboolean applycolor = true;
9788                         float one = 1.0;
9789
9790                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9791
9792                         r_refdef.lightmapintensity = 1;
9793                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9794                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9795                 }
9796                 else if (FAKELIGHT_ENABLED)
9797                 {
9798                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9799
9800                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9801                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9802                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9803                 }
9804                 else
9805                 {
9806                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9807
9808                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9809                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9810                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9811                 }
9812
9813                 if(!rsurface.passcolor4f)
9814                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9815
9816                 RSurf_DrawBatch_GL11_ApplyAmbient();
9817                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9818                 if(r_refdef.fogenabled)
9819                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9820                 RSurf_DrawBatch_GL11_ClampColor();
9821
9822                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9823                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9824                 RSurf_DrawBatch();
9825         }
9826         else if (!r_refdef.view.showdebug)
9827         {
9828                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9829                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9830                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9831                 {
9832                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9833                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9834                 }
9835                 R_Mesh_PrepareVertices_Generic_Unlock();
9836                 RSurf_DrawBatch();
9837         }
9838         else if (r_showsurfaces.integer == 4)
9839         {
9840                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9841                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9842                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9843                 {
9844                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9845                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9846                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9847                 }
9848                 R_Mesh_PrepareVertices_Generic_Unlock();
9849                 RSurf_DrawBatch();
9850         }
9851         else if (r_showsurfaces.integer == 2)
9852         {
9853                 const int *e;
9854                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9855                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9856                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9857                 {
9858                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9859                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9860                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9861                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9862                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9863                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9864                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9865                 }
9866                 R_Mesh_PrepareVertices_Generic_Unlock();
9867                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9868         }
9869         else
9870         {
9871                 int texturesurfaceindex;
9872                 int k;
9873                 const msurface_t *surface;
9874                 float surfacecolor4f[4];
9875                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9876                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9877                 vi = 0;
9878                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9879                 {
9880                         surface = texturesurfacelist[texturesurfaceindex];
9881                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9882                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9883                         for (j = 0;j < surface->num_vertices;j++)
9884                         {
9885                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9886                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9887                                 vi++;
9888                         }
9889                 }
9890                 R_Mesh_PrepareVertices_Generic_Unlock();
9891                 RSurf_DrawBatch();
9892         }
9893 }
9894
9895 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9896 {
9897         CHECKGLERROR
9898         RSurf_SetupDepthAndCulling();
9899         if (r_showsurfaces.integer)
9900         {
9901                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9902                 return;
9903         }
9904         switch (vid.renderpath)
9905         {
9906         case RENDERPATH_GL20:
9907         case RENDERPATH_D3D9:
9908         case RENDERPATH_D3D10:
9909         case RENDERPATH_D3D11:
9910         case RENDERPATH_SOFT:
9911         case RENDERPATH_GLES2:
9912                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9913                 break;
9914         case RENDERPATH_GL13:
9915         case RENDERPATH_GLES1:
9916                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9917                 break;
9918         case RENDERPATH_GL11:
9919                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9920                 break;
9921         }
9922         CHECKGLERROR
9923 }
9924
9925 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9926 {
9927         CHECKGLERROR
9928         RSurf_SetupDepthAndCulling();
9929         if (r_showsurfaces.integer)
9930         {
9931                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9932                 return;
9933         }
9934         switch (vid.renderpath)
9935         {
9936         case RENDERPATH_GL20:
9937         case RENDERPATH_D3D9:
9938         case RENDERPATH_D3D10:
9939         case RENDERPATH_D3D11:
9940         case RENDERPATH_SOFT:
9941         case RENDERPATH_GLES2:
9942                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9943                 break;
9944         case RENDERPATH_GL13:
9945         case RENDERPATH_GLES1:
9946                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9947                 break;
9948         case RENDERPATH_GL11:
9949                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9950                 break;
9951         }
9952         CHECKGLERROR
9953 }
9954
9955 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9956 {
9957         int i, j;
9958         int texturenumsurfaces, endsurface;
9959         texture_t *texture;
9960         const msurface_t *surface;
9961 #define MAXBATCH_TRANSPARENTSURFACES 256
9962         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9963
9964         // if the model is static it doesn't matter what value we give for
9965         // wantnormals and wanttangents, so this logic uses only rules applicable
9966         // to a model, knowing that they are meaningless otherwise
9967         if (ent == r_refdef.scene.worldentity)
9968                 RSurf_ActiveWorldEntity();
9969         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9970                 RSurf_ActiveModelEntity(ent, false, false, false);
9971         else
9972         {
9973                 switch (vid.renderpath)
9974                 {
9975                 case RENDERPATH_GL20:
9976                 case RENDERPATH_D3D9:
9977                 case RENDERPATH_D3D10:
9978                 case RENDERPATH_D3D11:
9979                 case RENDERPATH_SOFT:
9980                 case RENDERPATH_GLES2:
9981                         RSurf_ActiveModelEntity(ent, true, true, false);
9982                         break;
9983                 case RENDERPATH_GL11:
9984                 case RENDERPATH_GL13:
9985                 case RENDERPATH_GLES1:
9986                         RSurf_ActiveModelEntity(ent, true, false, false);
9987                         break;
9988                 }
9989         }
9990
9991         if (r_transparentdepthmasking.integer)
9992         {
9993                 qboolean setup = false;
9994                 for (i = 0;i < numsurfaces;i = j)
9995                 {
9996                         j = i + 1;
9997                         surface = rsurface.modelsurfaces + surfacelist[i];
9998                         texture = surface->texture;
9999                         rsurface.texture = R_GetCurrentTexture(texture);
10000                         rsurface.lightmaptexture = NULL;
10001                         rsurface.deluxemaptexture = NULL;
10002                         rsurface.uselightmaptexture = false;
10003                         // scan ahead until we find a different texture
10004                         endsurface = min(i + 1024, numsurfaces);
10005                         texturenumsurfaces = 0;
10006                         texturesurfacelist[texturenumsurfaces++] = surface;
10007                         for (;j < endsurface;j++)
10008                         {
10009                                 surface = rsurface.modelsurfaces + surfacelist[j];
10010                                 if (texture != surface->texture)
10011                                         break;
10012                                 texturesurfacelist[texturenumsurfaces++] = surface;
10013                         }
10014                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10015                                 continue;
10016                         // render the range of surfaces as depth
10017                         if (!setup)
10018                         {
10019                                 setup = true;
10020                                 GL_ColorMask(0,0,0,0);
10021                                 GL_Color(1,1,1,1);
10022                                 GL_DepthTest(true);
10023                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10024                                 GL_DepthMask(true);
10025 //                              R_Mesh_ResetTextureState();
10026                                 R_SetupShader_DepthOrShadow();
10027                         }
10028                         RSurf_SetupDepthAndCulling();
10029                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10030                         if (rsurface.batchvertex3fbuffer)
10031                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10032                         else
10033                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10034                         RSurf_DrawBatch();
10035                 }
10036                 if (setup)
10037                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10038         }
10039
10040         for (i = 0;i < numsurfaces;i = j)
10041         {
10042                 j = i + 1;
10043                 surface = rsurface.modelsurfaces + surfacelist[i];
10044                 texture = surface->texture;
10045                 rsurface.texture = R_GetCurrentTexture(texture);
10046                 // scan ahead until we find a different texture
10047                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10048                 texturenumsurfaces = 0;
10049                 texturesurfacelist[texturenumsurfaces++] = surface;
10050                 if(FAKELIGHT_ENABLED)
10051                 {
10052                         rsurface.lightmaptexture = NULL;
10053                         rsurface.deluxemaptexture = NULL;
10054                         rsurface.uselightmaptexture = false;
10055                         for (;j < endsurface;j++)
10056                         {
10057                                 surface = rsurface.modelsurfaces + surfacelist[j];
10058                                 if (texture != surface->texture)
10059                                         break;
10060                                 texturesurfacelist[texturenumsurfaces++] = surface;
10061                         }
10062                 }
10063                 else
10064                 {
10065                         rsurface.lightmaptexture = surface->lightmaptexture;
10066                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10067                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10068                         for (;j < endsurface;j++)
10069                         {
10070                                 surface = rsurface.modelsurfaces + surfacelist[j];
10071                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10072                                         break;
10073                                 texturesurfacelist[texturenumsurfaces++] = surface;
10074                         }
10075                 }
10076                 // render the range of surfaces
10077                 if (ent == r_refdef.scene.worldentity)
10078                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10079                 else
10080                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10081         }
10082         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10083 }
10084
10085 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10086 {
10087         // transparent surfaces get pushed off into the transparent queue
10088         int surfacelistindex;
10089         const msurface_t *surface;
10090         vec3_t tempcenter, center;
10091         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10092         {
10093                 surface = texturesurfacelist[surfacelistindex];
10094                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10095                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10096                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10097                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10098                 if (queueentity->transparent_offset) // transparent offset
10099                 {
10100                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10101                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10102                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10103                 }
10104                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10105         }
10106 }
10107
10108 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10109 {
10110         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10111                 return;
10112         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10113                 return;
10114         RSurf_SetupDepthAndCulling();
10115         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10116         if (rsurface.batchvertex3fbuffer)
10117                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10118         else
10119                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10120         RSurf_DrawBatch();
10121 }
10122
10123 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10124 {
10125         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10126         CHECKGLERROR
10127         if (depthonly)
10128                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10129         else if (prepass)
10130         {
10131                 if (!rsurface.texture->currentnumlayers)
10132                         return;
10133                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10134                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10135                 else
10136                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10137         }
10138         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10139                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10140         else if (!rsurface.texture->currentnumlayers)
10141                 return;
10142         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10143         {
10144                 // in the deferred case, transparent surfaces were queued during prepass
10145                 if (!r_shadow_usingdeferredprepass)
10146                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10147         }
10148         else
10149         {
10150                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10151                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10152         }
10153         CHECKGLERROR
10154 }
10155
10156 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10157 {
10158         int i, j;
10159         texture_t *texture;
10160         R_FrameData_SetMark();
10161         // break the surface list down into batches by texture and use of lightmapping
10162         for (i = 0;i < numsurfaces;i = j)
10163         {
10164                 j = i + 1;
10165                 // texture is the base texture pointer, rsurface.texture is the
10166                 // current frame/skin the texture is directing us to use (for example
10167                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10168                 // use skin 1 instead)
10169                 texture = surfacelist[i]->texture;
10170                 rsurface.texture = R_GetCurrentTexture(texture);
10171                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10172                 {
10173                         // if this texture is not the kind we want, skip ahead to the next one
10174                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10175                                 ;
10176                         continue;
10177                 }
10178                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10179                 {
10180                         rsurface.lightmaptexture = NULL;
10181                         rsurface.deluxemaptexture = NULL;
10182                         rsurface.uselightmaptexture = false;
10183                         // simply scan ahead until we find a different texture or lightmap state
10184                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10185                                 ;
10186                 }
10187                 else
10188                 {
10189                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10190                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10191                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10192                         // simply scan ahead until we find a different texture or lightmap state
10193                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10194                                 ;
10195                 }
10196                 // render the range of surfaces
10197                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10198         }
10199         R_FrameData_ReturnToMark();
10200 }
10201
10202 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10203 {
10204         CHECKGLERROR
10205         if (depthonly)
10206                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10207         else if (prepass)
10208         {
10209                 if (!rsurface.texture->currentnumlayers)
10210                         return;
10211                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10212                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10213                 else
10214                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10215         }
10216         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10217                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10218         else if (!rsurface.texture->currentnumlayers)
10219                 return;
10220         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10221         {
10222                 // in the deferred case, transparent surfaces were queued during prepass
10223                 if (!r_shadow_usingdeferredprepass)
10224                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10225         }
10226         else
10227         {
10228                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10229                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10230         }
10231         CHECKGLERROR
10232 }
10233
10234 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10235 {
10236         int i, j;
10237         texture_t *texture;
10238         R_FrameData_SetMark();
10239         // break the surface list down into batches by texture and use of lightmapping
10240         for (i = 0;i < numsurfaces;i = j)
10241         {
10242                 j = i + 1;
10243                 // texture is the base texture pointer, rsurface.texture is the
10244                 // current frame/skin the texture is directing us to use (for example
10245                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10246                 // use skin 1 instead)
10247                 texture = surfacelist[i]->texture;
10248                 rsurface.texture = R_GetCurrentTexture(texture);
10249                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10250                 {
10251                         // if this texture is not the kind we want, skip ahead to the next one
10252                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10253                                 ;
10254                         continue;
10255                 }
10256                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10257                 {
10258                         rsurface.lightmaptexture = NULL;
10259                         rsurface.deluxemaptexture = NULL;
10260                         rsurface.uselightmaptexture = false;
10261                         // simply scan ahead until we find a different texture or lightmap state
10262                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10263                                 ;
10264                 }
10265                 else
10266                 {
10267                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10268                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10269                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10270                         // simply scan ahead until we find a different texture or lightmap state
10271                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10272                                 ;
10273                 }
10274                 // render the range of surfaces
10275                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10276         }
10277         R_FrameData_ReturnToMark();
10278 }
10279
10280 float locboxvertex3f[6*4*3] =
10281 {
10282         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10283         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10284         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10285         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10286         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10287         1,0,0, 0,0,0, 0,1,0, 1,1,0
10288 };
10289
10290 unsigned short locboxelements[6*2*3] =
10291 {
10292          0, 1, 2, 0, 2, 3,
10293          4, 5, 6, 4, 6, 7,
10294          8, 9,10, 8,10,11,
10295         12,13,14, 12,14,15,
10296         16,17,18, 16,18,19,
10297         20,21,22, 20,22,23
10298 };
10299
10300 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10301 {
10302         int i, j;
10303         cl_locnode_t *loc = (cl_locnode_t *)ent;
10304         vec3_t mins, size;
10305         float vertex3f[6*4*3];
10306         CHECKGLERROR
10307         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10308         GL_DepthMask(false);
10309         GL_DepthRange(0, 1);
10310         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10311         GL_DepthTest(true);
10312         GL_CullFace(GL_NONE);
10313         R_EntityMatrix(&identitymatrix);
10314
10315 //      R_Mesh_ResetTextureState();
10316
10317         i = surfacelist[0];
10318         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10319                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10320                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10321                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10322
10323         if (VectorCompare(loc->mins, loc->maxs))
10324         {
10325                 VectorSet(size, 2, 2, 2);
10326                 VectorMA(loc->mins, -0.5f, size, mins);
10327         }
10328         else
10329         {
10330                 VectorCopy(loc->mins, mins);
10331                 VectorSubtract(loc->maxs, loc->mins, size);
10332         }
10333
10334         for (i = 0;i < 6*4*3;)
10335                 for (j = 0;j < 3;j++, i++)
10336                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10337
10338         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10339         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10340         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10341 }
10342
10343 void R_DrawLocs(void)
10344 {
10345         int index;
10346         cl_locnode_t *loc, *nearestloc;
10347         vec3_t center;
10348         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10349         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10350         {
10351                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10352                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10353         }
10354 }
10355
10356 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10357 {
10358         if (decalsystem->decals)
10359                 Mem_Free(decalsystem->decals);
10360         memset(decalsystem, 0, sizeof(*decalsystem));
10361 }
10362
10363 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)
10364 {
10365         tridecal_t *decal;
10366         tridecal_t *decals;
10367         int i;
10368
10369         // expand or initialize the system
10370         if (decalsystem->maxdecals <= decalsystem->numdecals)
10371         {
10372                 decalsystem_t old = *decalsystem;
10373                 qboolean useshortelements;
10374                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10375                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10376                 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)));
10377                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10378                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10379                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10380                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10381                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10382                 if (decalsystem->numdecals)
10383                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10384                 if (old.decals)
10385                         Mem_Free(old.decals);
10386                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10387                         decalsystem->element3i[i] = i;
10388                 if (useshortelements)
10389                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10390                                 decalsystem->element3s[i] = i;
10391         }
10392
10393         // grab a decal and search for another free slot for the next one
10394         decals = decalsystem->decals;
10395         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10396         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10397                 ;
10398         decalsystem->freedecal = i;
10399         if (decalsystem->numdecals <= i)
10400                 decalsystem->numdecals = i + 1;
10401
10402         // initialize the decal
10403         decal->lived = 0;
10404         decal->triangleindex = triangleindex;
10405         decal->surfaceindex = surfaceindex;
10406         decal->decalsequence = decalsequence;
10407         decal->color4f[0][0] = c0[0];
10408         decal->color4f[0][1] = c0[1];
10409         decal->color4f[0][2] = c0[2];
10410         decal->color4f[0][3] = 1;
10411         decal->color4f[1][0] = c1[0];
10412         decal->color4f[1][1] = c1[1];
10413         decal->color4f[1][2] = c1[2];
10414         decal->color4f[1][3] = 1;
10415         decal->color4f[2][0] = c2[0];
10416         decal->color4f[2][1] = c2[1];
10417         decal->color4f[2][2] = c2[2];
10418         decal->color4f[2][3] = 1;
10419         decal->vertex3f[0][0] = v0[0];
10420         decal->vertex3f[0][1] = v0[1];
10421         decal->vertex3f[0][2] = v0[2];
10422         decal->vertex3f[1][0] = v1[0];
10423         decal->vertex3f[1][1] = v1[1];
10424         decal->vertex3f[1][2] = v1[2];
10425         decal->vertex3f[2][0] = v2[0];
10426         decal->vertex3f[2][1] = v2[1];
10427         decal->vertex3f[2][2] = v2[2];
10428         decal->texcoord2f[0][0] = t0[0];
10429         decal->texcoord2f[0][1] = t0[1];
10430         decal->texcoord2f[1][0] = t1[0];
10431         decal->texcoord2f[1][1] = t1[1];
10432         decal->texcoord2f[2][0] = t2[0];
10433         decal->texcoord2f[2][1] = t2[1];
10434         TriangleNormal(v0, v1, v2, decal->plane);
10435         VectorNormalize(decal->plane);
10436         decal->plane[3] = DotProduct(v0, decal->plane);
10437 }
10438
10439 extern cvar_t cl_decals_bias;
10440 extern cvar_t cl_decals_models;
10441 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10442 // baseparms, parms, temps
10443 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)
10444 {
10445         int cornerindex;
10446         int index;
10447         float v[9][3];
10448         const float *vertex3f;
10449         const float *normal3f;
10450         int numpoints;
10451         float points[2][9][3];
10452         float temp[3];
10453         float tc[9][2];
10454         float f;
10455         float c[9][4];
10456         const int *e;
10457
10458         e = rsurface.modelelement3i + 3*triangleindex;
10459
10460         vertex3f = rsurface.modelvertex3f;
10461         normal3f = rsurface.modelnormal3f;
10462
10463         if (normal3f)
10464         {
10465                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10466                 {
10467                         index = 3*e[cornerindex];
10468                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10469                 }
10470         }
10471         else
10472         {
10473                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10474                 {
10475                         index = 3*e[cornerindex];
10476                         VectorCopy(vertex3f + index, v[cornerindex]);
10477                 }
10478         }
10479
10480         // cull backfaces
10481         //TriangleNormal(v[0], v[1], v[2], normal);
10482         //if (DotProduct(normal, localnormal) < 0.0f)
10483         //      continue;
10484         // clip by each of the box planes formed from the projection matrix
10485         // if anything survives, we emit the decal
10486         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]);
10487         if (numpoints < 3)
10488                 return;
10489         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]);
10490         if (numpoints < 3)
10491                 return;
10492         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]);
10493         if (numpoints < 3)
10494                 return;
10495         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]);
10496         if (numpoints < 3)
10497                 return;
10498         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]);
10499         if (numpoints < 3)
10500                 return;
10501         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]);
10502         if (numpoints < 3)
10503                 return;
10504         // some part of the triangle survived, so we have to accept it...
10505         if (dynamic)
10506         {
10507                 // dynamic always uses the original triangle
10508                 numpoints = 3;
10509                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10510                 {
10511                         index = 3*e[cornerindex];
10512                         VectorCopy(vertex3f + index, v[cornerindex]);
10513                 }
10514         }
10515         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10516         {
10517                 // convert vertex positions to texcoords
10518                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10519                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10520                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10521                 // calculate distance fade from the projection origin
10522                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10523                 f = bound(0.0f, f, 1.0f);
10524                 c[cornerindex][0] = r * f;
10525                 c[cornerindex][1] = g * f;
10526                 c[cornerindex][2] = b * f;
10527                 c[cornerindex][3] = 1.0f;
10528                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10529         }
10530         if (dynamic)
10531                 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);
10532         else
10533                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10534                         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);
10535 }
10536 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)
10537 {
10538         matrix4x4_t projection;
10539         decalsystem_t *decalsystem;
10540         qboolean dynamic;
10541         dp_model_t *model;
10542         const msurface_t *surface;
10543         const msurface_t *surfaces;
10544         const int *surfacelist;
10545         const texture_t *texture;
10546         int numtriangles;
10547         int numsurfacelist;
10548         int surfacelistindex;
10549         int surfaceindex;
10550         int triangleindex;
10551         float localorigin[3];
10552         float localnormal[3];
10553         float localmins[3];
10554         float localmaxs[3];
10555         float localsize;
10556         //float normal[3];
10557         float planes[6][4];
10558         float angles[3];
10559         bih_t *bih;
10560         int bih_triangles_count;
10561         int bih_triangles[256];
10562         int bih_surfaces[256];
10563
10564         decalsystem = &ent->decalsystem;
10565         model = ent->model;
10566         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10567         {
10568                 R_DecalSystem_Reset(&ent->decalsystem);
10569                 return;
10570         }
10571
10572         if (!model->brush.data_leafs && !cl_decals_models.integer)
10573         {
10574                 if (decalsystem->model)
10575                         R_DecalSystem_Reset(decalsystem);
10576                 return;
10577         }
10578
10579         if (decalsystem->model != model)
10580                 R_DecalSystem_Reset(decalsystem);
10581         decalsystem->model = model;
10582
10583         RSurf_ActiveModelEntity(ent, true, false, false);
10584
10585         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10586         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10587         VectorNormalize(localnormal);
10588         localsize = worldsize*rsurface.inversematrixscale;
10589         localmins[0] = localorigin[0] - localsize;
10590         localmins[1] = localorigin[1] - localsize;
10591         localmins[2] = localorigin[2] - localsize;
10592         localmaxs[0] = localorigin[0] + localsize;
10593         localmaxs[1] = localorigin[1] + localsize;
10594         localmaxs[2] = localorigin[2] + localsize;
10595
10596         //VectorCopy(localnormal, planes[4]);
10597         //VectorVectors(planes[4], planes[2], planes[0]);
10598         AnglesFromVectors(angles, localnormal, NULL, false);
10599         AngleVectors(angles, planes[0], planes[2], planes[4]);
10600         VectorNegate(planes[0], planes[1]);
10601         VectorNegate(planes[2], planes[3]);
10602         VectorNegate(planes[4], planes[5]);
10603         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10604         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10605         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10606         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10607         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10608         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10609
10610 #if 1
10611 // works
10612 {
10613         matrix4x4_t forwardprojection;
10614         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10615         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10616 }
10617 #else
10618 // broken
10619 {
10620         float projectionvector[4][3];
10621         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10622         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10623         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10624         projectionvector[0][0] = planes[0][0] * ilocalsize;
10625         projectionvector[0][1] = planes[1][0] * ilocalsize;
10626         projectionvector[0][2] = planes[2][0] * ilocalsize;
10627         projectionvector[1][0] = planes[0][1] * ilocalsize;
10628         projectionvector[1][1] = planes[1][1] * ilocalsize;
10629         projectionvector[1][2] = planes[2][1] * ilocalsize;
10630         projectionvector[2][0] = planes[0][2] * ilocalsize;
10631         projectionvector[2][1] = planes[1][2] * ilocalsize;
10632         projectionvector[2][2] = planes[2][2] * ilocalsize;
10633         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10634         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10635         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10636         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10637 }
10638 #endif
10639
10640         dynamic = model->surfmesh.isanimated;
10641         numsurfacelist = model->nummodelsurfaces;
10642         surfacelist = model->sortedmodelsurfaces;
10643         surfaces = model->data_surfaces;
10644
10645         bih = NULL;
10646         bih_triangles_count = -1;
10647         if(!dynamic)
10648         {
10649                 if(model->render_bih.numleafs)
10650                         bih = &model->render_bih;
10651                 else if(model->collision_bih.numleafs)
10652                         bih = &model->collision_bih;
10653         }
10654         if(bih)
10655                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10656         if(bih_triangles_count == 0)
10657                 return;
10658         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10659                 return;
10660         if(bih_triangles_count > 0)
10661         {
10662                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10663                 {
10664                         surfaceindex = bih_surfaces[triangleindex];
10665                         surface = surfaces + surfaceindex;
10666                         texture = surface->texture;
10667                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10668                                 continue;
10669                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10670                                 continue;
10671                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10672                 }
10673         }
10674         else
10675         {
10676                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10677                 {
10678                         surfaceindex = surfacelist[surfacelistindex];
10679                         surface = surfaces + surfaceindex;
10680                         // check cull box first because it rejects more than any other check
10681                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10682                                 continue;
10683                         // skip transparent surfaces
10684                         texture = surface->texture;
10685                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10686                                 continue;
10687                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10688                                 continue;
10689                         numtriangles = surface->num_triangles;
10690                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10691                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10692                 }
10693         }
10694 }
10695
10696 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10697 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)
10698 {
10699         int renderentityindex;
10700         float worldmins[3];
10701         float worldmaxs[3];
10702         entity_render_t *ent;
10703
10704         if (!cl_decals_newsystem.integer)
10705                 return;
10706
10707         worldmins[0] = worldorigin[0] - worldsize;
10708         worldmins[1] = worldorigin[1] - worldsize;
10709         worldmins[2] = worldorigin[2] - worldsize;
10710         worldmaxs[0] = worldorigin[0] + worldsize;
10711         worldmaxs[1] = worldorigin[1] + worldsize;
10712         worldmaxs[2] = worldorigin[2] + worldsize;
10713
10714         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10715
10716         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10717         {
10718                 ent = r_refdef.scene.entities[renderentityindex];
10719                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10720                         continue;
10721
10722                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10723         }
10724 }
10725
10726 typedef struct r_decalsystem_splatqueue_s
10727 {
10728         vec3_t worldorigin;
10729         vec3_t worldnormal;
10730         float color[4];
10731         float tcrange[4];
10732         float worldsize;
10733         int decalsequence;
10734 }
10735 r_decalsystem_splatqueue_t;
10736
10737 int r_decalsystem_numqueued = 0;
10738 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10739
10740 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)
10741 {
10742         r_decalsystem_splatqueue_t *queue;
10743
10744         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10745                 return;
10746
10747         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10748         VectorCopy(worldorigin, queue->worldorigin);
10749         VectorCopy(worldnormal, queue->worldnormal);
10750         Vector4Set(queue->color, r, g, b, a);
10751         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10752         queue->worldsize = worldsize;
10753         queue->decalsequence = cl.decalsequence++;
10754 }
10755
10756 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10757 {
10758         int i;
10759         r_decalsystem_splatqueue_t *queue;
10760
10761         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10762                 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);
10763         r_decalsystem_numqueued = 0;
10764 }
10765
10766 extern cvar_t cl_decals_max;
10767 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10768 {
10769         int i;
10770         decalsystem_t *decalsystem = &ent->decalsystem;
10771         int numdecals;
10772         int killsequence;
10773         tridecal_t *decal;
10774         float frametime;
10775         float lifetime;
10776
10777         if (!decalsystem->numdecals)
10778                 return;
10779
10780         if (r_showsurfaces.integer)
10781                 return;
10782
10783         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10784         {
10785                 R_DecalSystem_Reset(decalsystem);
10786                 return;
10787         }
10788
10789         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10790         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10791
10792         if (decalsystem->lastupdatetime)
10793                 frametime = (cl.time - decalsystem->lastupdatetime);
10794         else
10795                 frametime = 0;
10796         decalsystem->lastupdatetime = cl.time;
10797         decal = decalsystem->decals;
10798         numdecals = decalsystem->numdecals;
10799
10800         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10801         {
10802                 if (decal->color4f[0][3])
10803                 {
10804                         decal->lived += frametime;
10805                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10806                         {
10807                                 memset(decal, 0, sizeof(*decal));
10808                                 if (decalsystem->freedecal > i)
10809                                         decalsystem->freedecal = i;
10810                         }
10811                 }
10812         }
10813         decal = decalsystem->decals;
10814         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10815                 numdecals--;
10816
10817         // collapse the array by shuffling the tail decals into the gaps
10818         for (;;)
10819         {
10820                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10821                         decalsystem->freedecal++;
10822                 if (decalsystem->freedecal == numdecals)
10823                         break;
10824                 decal[decalsystem->freedecal] = decal[--numdecals];
10825         }
10826
10827         decalsystem->numdecals = numdecals;
10828
10829         if (numdecals <= 0)
10830         {
10831                 // if there are no decals left, reset decalsystem
10832                 R_DecalSystem_Reset(decalsystem);
10833         }
10834 }
10835
10836 extern skinframe_t *decalskinframe;
10837 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10838 {
10839         int i;
10840         decalsystem_t *decalsystem = &ent->decalsystem;
10841         int numdecals;
10842         tridecal_t *decal;
10843         float faderate;
10844         float alpha;
10845         float *v3f;
10846         float *c4f;
10847         float *t2f;
10848         const int *e;
10849         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10850         int numtris = 0;
10851
10852         numdecals = decalsystem->numdecals;
10853         if (!numdecals)
10854                 return;
10855
10856         if (r_showsurfaces.integer)
10857                 return;
10858
10859         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10860         {
10861                 R_DecalSystem_Reset(decalsystem);
10862                 return;
10863         }
10864
10865         // if the model is static it doesn't matter what value we give for
10866         // wantnormals and wanttangents, so this logic uses only rules applicable
10867         // to a model, knowing that they are meaningless otherwise
10868         if (ent == r_refdef.scene.worldentity)
10869                 RSurf_ActiveWorldEntity();
10870         else
10871                 RSurf_ActiveModelEntity(ent, false, false, false);
10872
10873         decalsystem->lastupdatetime = cl.time;
10874         decal = decalsystem->decals;
10875
10876         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10877
10878         // update vertex positions for animated models
10879         v3f = decalsystem->vertex3f;
10880         c4f = decalsystem->color4f;
10881         t2f = decalsystem->texcoord2f;
10882         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10883         {
10884                 if (!decal->color4f[0][3])
10885                         continue;
10886
10887                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10888                         continue;
10889
10890                 // skip backfaces
10891                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10892                         continue;
10893
10894                 // update color values for fading decals
10895                 if (decal->lived >= cl_decals_time.value)
10896                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10897                 else
10898                         alpha = 1.0f;
10899
10900                 c4f[ 0] = decal->color4f[0][0] * alpha;
10901                 c4f[ 1] = decal->color4f[0][1] * alpha;
10902                 c4f[ 2] = decal->color4f[0][2] * alpha;
10903                 c4f[ 3] = 1;
10904                 c4f[ 4] = decal->color4f[1][0] * alpha;
10905                 c4f[ 5] = decal->color4f[1][1] * alpha;
10906                 c4f[ 6] = decal->color4f[1][2] * alpha;
10907                 c4f[ 7] = 1;
10908                 c4f[ 8] = decal->color4f[2][0] * alpha;
10909                 c4f[ 9] = decal->color4f[2][1] * alpha;
10910                 c4f[10] = decal->color4f[2][2] * alpha;
10911                 c4f[11] = 1;
10912
10913                 t2f[0] = decal->texcoord2f[0][0];
10914                 t2f[1] = decal->texcoord2f[0][1];
10915                 t2f[2] = decal->texcoord2f[1][0];
10916                 t2f[3] = decal->texcoord2f[1][1];
10917                 t2f[4] = decal->texcoord2f[2][0];
10918                 t2f[5] = decal->texcoord2f[2][1];
10919
10920                 // update vertex positions for animated models
10921                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10922                 {
10923                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10924                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10925                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10926                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10927                 }
10928                 else
10929                 {
10930                         VectorCopy(decal->vertex3f[0], v3f);
10931                         VectorCopy(decal->vertex3f[1], v3f + 3);
10932                         VectorCopy(decal->vertex3f[2], v3f + 6);
10933                 }
10934
10935                 if (r_refdef.fogenabled)
10936                 {
10937                         alpha = RSurf_FogVertex(v3f);
10938                         VectorScale(c4f, alpha, c4f);
10939                         alpha = RSurf_FogVertex(v3f + 3);
10940                         VectorScale(c4f + 4, alpha, c4f + 4);
10941                         alpha = RSurf_FogVertex(v3f + 6);
10942                         VectorScale(c4f + 8, alpha, c4f + 8);
10943                 }
10944
10945                 v3f += 9;
10946                 c4f += 12;
10947                 t2f += 6;
10948                 numtris++;
10949         }
10950
10951         if (numtris > 0)
10952         {
10953                 r_refdef.stats.drawndecals += numtris;
10954
10955                 // now render the decals all at once
10956                 // (this assumes they all use one particle font texture!)
10957                 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);
10958 //              R_Mesh_ResetTextureState();
10959                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10960                 GL_DepthMask(false);
10961                 GL_DepthRange(0, 1);
10962                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10963                 GL_DepthTest(true);
10964                 GL_CullFace(GL_NONE);
10965                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10966                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10967                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10968         }
10969 }
10970
10971 static void R_DrawModelDecals(void)
10972 {
10973         int i, numdecals;
10974
10975         // fade faster when there are too many decals
10976         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10977         for (i = 0;i < r_refdef.scene.numentities;i++)
10978                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10979
10980         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10981         for (i = 0;i < r_refdef.scene.numentities;i++)
10982                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10983                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10984
10985         R_DecalSystem_ApplySplatEntitiesQueue();
10986
10987         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10988         for (i = 0;i < r_refdef.scene.numentities;i++)
10989                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10990
10991         r_refdef.stats.totaldecals += numdecals;
10992
10993         if (r_showsurfaces.integer)
10994                 return;
10995
10996         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10997
10998         for (i = 0;i < r_refdef.scene.numentities;i++)
10999         {
11000                 if (!r_refdef.viewcache.entityvisible[i])
11001                         continue;
11002                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11003                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11004         }
11005 }
11006
11007 extern cvar_t mod_collision_bih;
11008 void R_DrawDebugModel(void)
11009 {
11010         entity_render_t *ent = rsurface.entity;
11011         int i, j, k, l, flagsmask;
11012         const msurface_t *surface;
11013         dp_model_t *model = ent->model;
11014         vec3_t v;
11015
11016         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11017                 return;
11018
11019         if (r_showoverdraw.value > 0)
11020         {
11021                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11022                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11023                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11024                 GL_DepthTest(false);
11025                 GL_DepthMask(false);
11026                 GL_DepthRange(0, 1);
11027                 GL_BlendFunc(GL_ONE, GL_ONE);
11028                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11029                 {
11030                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11031                                 continue;
11032                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11033                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11034                         {
11035                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11036                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11037                                 if (!rsurface.texture->currentlayers->depthmask)
11038                                         GL_Color(c, 0, 0, 1.0f);
11039                                 else if (ent == r_refdef.scene.worldentity)
11040                                         GL_Color(c, c, c, 1.0f);
11041                                 else
11042                                         GL_Color(0, c, 0, 1.0f);
11043                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11044                                 RSurf_DrawBatch();
11045                         }
11046                 }
11047                 rsurface.texture = NULL;
11048         }
11049
11050         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11051
11052 //      R_Mesh_ResetTextureState();
11053         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11054         GL_DepthRange(0, 1);
11055         GL_DepthTest(!r_showdisabledepthtest.integer);
11056         GL_DepthMask(false);
11057         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11058
11059         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11060         {
11061                 int triangleindex;
11062                 int bihleafindex;
11063                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11064                 const q3mbrush_t *brush;
11065                 const bih_t *bih = &model->collision_bih;
11066                 const bih_leaf_t *bihleaf;
11067                 float vertex3f[3][3];
11068                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11069                 cullbox = false;
11070                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11071                 {
11072                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11073                                 continue;
11074                         switch (bihleaf->type)
11075                         {
11076                         case BIH_BRUSH:
11077                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11078                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11079                                 {
11080                                         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);
11081                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11082                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11083                                 }
11084                                 break;
11085                         case BIH_COLLISIONTRIANGLE:
11086                                 triangleindex = bihleaf->itemindex;
11087                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11088                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11089                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11090                                 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);
11091                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11092                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11093                                 break;
11094                         case BIH_RENDERTRIANGLE:
11095                                 triangleindex = bihleaf->itemindex;
11096                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11097                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11098                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11099                                 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);
11100                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11101                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11102                                 break;
11103                         }
11104                 }
11105         }
11106
11107         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11108
11109         if (r_showtris.integer && qglPolygonMode)
11110         {
11111                 if (r_showdisabledepthtest.integer)
11112                 {
11113                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11114                         GL_DepthMask(false);
11115                 }
11116                 else
11117                 {
11118                         GL_BlendFunc(GL_ONE, GL_ZERO);
11119                         GL_DepthMask(true);
11120                 }
11121                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11122                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11123                 {
11124                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11125                                 continue;
11126                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11127                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11128                         {
11129                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11130                                 if (!rsurface.texture->currentlayers->depthmask)
11131                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11132                                 else if (ent == r_refdef.scene.worldentity)
11133                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11134                                 else
11135                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11136                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11137                                 RSurf_DrawBatch();
11138                         }
11139                 }
11140                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11141                 rsurface.texture = NULL;
11142         }
11143
11144         if (r_shownormals.value != 0 && qglBegin)
11145         {
11146                 if (r_showdisabledepthtest.integer)
11147                 {
11148                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11149                         GL_DepthMask(false);
11150                 }
11151                 else
11152                 {
11153                         GL_BlendFunc(GL_ONE, GL_ZERO);
11154                         GL_DepthMask(true);
11155                 }
11156                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11157                 {
11158                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11159                                 continue;
11160                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11161                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11162                         {
11163                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11164                                 qglBegin(GL_LINES);
11165                                 if (r_shownormals.value < 0)
11166                                 {
11167                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11168                                         {
11169                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11170                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11171                                                 qglVertex3f(v[0], v[1], v[2]);
11172                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11173                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11174                                                 qglVertex3f(v[0], v[1], v[2]);
11175                                         }
11176                                 }
11177                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11178                                 {
11179                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11180                                         {
11181                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11182                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11183                                                 qglVertex3f(v[0], v[1], v[2]);
11184                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11185                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11186                                                 qglVertex3f(v[0], v[1], v[2]);
11187                                         }
11188                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11189                                         {
11190                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11191                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11192                                                 qglVertex3f(v[0], v[1], v[2]);
11193                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11194                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11195                                                 qglVertex3f(v[0], v[1], v[2]);
11196                                         }
11197                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11198                                         {
11199                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11200                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11201                                                 qglVertex3f(v[0], v[1], v[2]);
11202                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11203                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11204                                                 qglVertex3f(v[0], v[1], v[2]);
11205                                         }
11206                                 }
11207                                 qglEnd();
11208                                 CHECKGLERROR
11209                         }
11210                 }
11211                 rsurface.texture = NULL;
11212         }
11213 }
11214
11215 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11216 int r_maxsurfacelist = 0;
11217 const msurface_t **r_surfacelist = NULL;
11218 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11219 {
11220         int i, j, endj, flagsmask;
11221         dp_model_t *model = r_refdef.scene.worldmodel;
11222         msurface_t *surfaces;
11223         unsigned char *update;
11224         int numsurfacelist = 0;
11225         if (model == NULL)
11226                 return;
11227
11228         if (r_maxsurfacelist < model->num_surfaces)
11229         {
11230                 r_maxsurfacelist = model->num_surfaces;
11231                 if (r_surfacelist)
11232                         Mem_Free((msurface_t**)r_surfacelist);
11233                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11234         }
11235
11236         RSurf_ActiveWorldEntity();
11237
11238         surfaces = model->data_surfaces;
11239         update = model->brushq1.lightmapupdateflags;
11240
11241         // update light styles on this submodel
11242         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11243         {
11244                 model_brush_lightstyleinfo_t *style;
11245                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11246                 {
11247                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11248                         {
11249                                 int *list = style->surfacelist;
11250                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11251                                 for (j = 0;j < style->numsurfaces;j++)
11252                                         update[list[j]] = true;
11253                         }
11254                 }
11255         }
11256
11257         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11258
11259         if (debug)
11260         {
11261                 R_DrawDebugModel();
11262                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11263                 return;
11264         }
11265
11266         rsurface.lightmaptexture = NULL;
11267         rsurface.deluxemaptexture = NULL;
11268         rsurface.uselightmaptexture = false;
11269         rsurface.texture = NULL;
11270         rsurface.rtlight = NULL;
11271         numsurfacelist = 0;
11272         // add visible surfaces to draw list
11273         for (i = 0;i < model->nummodelsurfaces;i++)
11274         {
11275                 j = model->sortedmodelsurfaces[i];
11276                 if (r_refdef.viewcache.world_surfacevisible[j])
11277                         r_surfacelist[numsurfacelist++] = surfaces + j;
11278         }
11279         // update lightmaps if needed
11280         if (model->brushq1.firstrender)
11281         {
11282                 model->brushq1.firstrender = false;
11283                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11284                         if (update[j])
11285                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11286         }
11287         else if (update)
11288         {
11289                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11290                         if (r_refdef.viewcache.world_surfacevisible[j])
11291                                 if (update[j])
11292                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11293         }
11294         // don't do anything if there were no surfaces
11295         if (!numsurfacelist)
11296         {
11297                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11298                 return;
11299         }
11300         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11301
11302         // add to stats if desired
11303         if (r_speeds.integer && !skysurfaces && !depthonly)
11304         {
11305                 r_refdef.stats.world_surfaces += numsurfacelist;
11306                 for (j = 0;j < numsurfacelist;j++)
11307                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11308         }
11309
11310         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11311 }
11312
11313 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11314 {
11315         int i, j, endj, flagsmask;
11316         dp_model_t *model = ent->model;
11317         msurface_t *surfaces;
11318         unsigned char *update;
11319         int numsurfacelist = 0;
11320         if (model == NULL)
11321                 return;
11322
11323         if (r_maxsurfacelist < model->num_surfaces)
11324         {
11325                 r_maxsurfacelist = model->num_surfaces;
11326                 if (r_surfacelist)
11327                         Mem_Free((msurface_t **)r_surfacelist);
11328                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11329         }
11330
11331         // if the model is static it doesn't matter what value we give for
11332         // wantnormals and wanttangents, so this logic uses only rules applicable
11333         // to a model, knowing that they are meaningless otherwise
11334         if (ent == r_refdef.scene.worldentity)
11335                 RSurf_ActiveWorldEntity();
11336         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11337                 RSurf_ActiveModelEntity(ent, false, false, false);
11338         else if (prepass)
11339                 RSurf_ActiveModelEntity(ent, true, true, true);
11340         else if (depthonly)
11341         {
11342                 switch (vid.renderpath)
11343                 {
11344                 case RENDERPATH_GL20:
11345                 case RENDERPATH_D3D9:
11346                 case RENDERPATH_D3D10:
11347                 case RENDERPATH_D3D11:
11348                 case RENDERPATH_SOFT:
11349                 case RENDERPATH_GLES2:
11350                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11351                         break;
11352                 case RENDERPATH_GL11:
11353                 case RENDERPATH_GL13:
11354                 case RENDERPATH_GLES1:
11355                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11356                         break;
11357                 }
11358         }
11359         else
11360         {
11361                 switch (vid.renderpath)
11362                 {
11363                 case RENDERPATH_GL20:
11364                 case RENDERPATH_D3D9:
11365                 case RENDERPATH_D3D10:
11366                 case RENDERPATH_D3D11:
11367                 case RENDERPATH_SOFT:
11368                 case RENDERPATH_GLES2:
11369                         RSurf_ActiveModelEntity(ent, true, true, false);
11370                         break;
11371                 case RENDERPATH_GL11:
11372                 case RENDERPATH_GL13:
11373                 case RENDERPATH_GLES1:
11374                         RSurf_ActiveModelEntity(ent, true, false, false);
11375                         break;
11376                 }
11377         }
11378
11379         surfaces = model->data_surfaces;
11380         update = model->brushq1.lightmapupdateflags;
11381
11382         // update light styles
11383         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11384         {
11385                 model_brush_lightstyleinfo_t *style;
11386                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11387                 {
11388                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11389                         {
11390                                 int *list = style->surfacelist;
11391                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11392                                 for (j = 0;j < style->numsurfaces;j++)
11393                                         update[list[j]] = true;
11394                         }
11395                 }
11396         }
11397
11398         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11399
11400         if (debug)
11401         {
11402                 R_DrawDebugModel();
11403                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11404                 return;
11405         }
11406
11407         rsurface.lightmaptexture = NULL;
11408         rsurface.deluxemaptexture = NULL;
11409         rsurface.uselightmaptexture = false;
11410         rsurface.texture = NULL;
11411         rsurface.rtlight = NULL;
11412         numsurfacelist = 0;
11413         // add visible surfaces to draw list
11414         for (i = 0;i < model->nummodelsurfaces;i++)
11415                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11416         // don't do anything if there were no surfaces
11417         if (!numsurfacelist)
11418         {
11419                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11420                 return;
11421         }
11422         // update lightmaps if needed
11423         if (update)
11424         {
11425                 int updated = 0;
11426                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11427                 {
11428                         if (update[j])
11429                         {
11430                                 updated++;
11431                                 R_BuildLightMap(ent, surfaces + j);
11432                         }
11433                 }
11434         }
11435         if (update)
11436                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11437                         if (update[j])
11438                                 R_BuildLightMap(ent, surfaces + j);
11439         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11440
11441         // add to stats if desired
11442         if (r_speeds.integer && !skysurfaces && !depthonly)
11443         {
11444                 r_refdef.stats.entities_surfaces += numsurfacelist;
11445                 for (j = 0;j < numsurfacelist;j++)
11446                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11447         }
11448
11449         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11450 }
11451
11452 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11453 {
11454         static texture_t texture;
11455         static msurface_t surface;
11456         const msurface_t *surfacelist = &surface;
11457
11458         // fake enough texture and surface state to render this geometry
11459
11460         texture.update_lastrenderframe = -1; // regenerate this texture
11461         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11462         texture.currentskinframe = skinframe;
11463         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11464         texture.offsetmapping = OFFSETMAPPING_OFF;
11465         texture.offsetscale = 1;
11466         texture.specularscalemod = 1;
11467         texture.specularpowermod = 1;
11468
11469         surface.texture = &texture;
11470         surface.num_triangles = numtriangles;
11471         surface.num_firsttriangle = firsttriangle;
11472         surface.num_vertices = numvertices;
11473         surface.num_firstvertex = firstvertex;
11474
11475         // now render it
11476         rsurface.texture = R_GetCurrentTexture(surface.texture);
11477         rsurface.lightmaptexture = NULL;
11478         rsurface.deluxemaptexture = NULL;
11479         rsurface.uselightmaptexture = false;
11480         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11481 }
11482
11483 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)
11484 {
11485         static msurface_t surface;
11486         const msurface_t *surfacelist = &surface;
11487
11488         // fake enough texture and surface state to render this geometry
11489         surface.texture = texture;
11490         surface.num_triangles = numtriangles;
11491         surface.num_firsttriangle = firsttriangle;
11492         surface.num_vertices = numvertices;
11493         surface.num_firstvertex = firstvertex;
11494
11495         // now render it
11496         rsurface.texture = R_GetCurrentTexture(surface.texture);
11497         rsurface.lightmaptexture = NULL;
11498         rsurface.deluxemaptexture = NULL;
11499         rsurface.uselightmaptexture = false;
11500         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11501 }