]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
new cvar: r_glsl_offsetmapping_reliefmapping_refinesteps (default 5)
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
119 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
120 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
121
122 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
123 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
124 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
125 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
126 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
127 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
128 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
129 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130
131 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
132 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
133
134 cvar_t r_texture_sRGB_2d = {0, "r_texture_sRGB_2d", "0", "load textures as sRGB"};
135 cvar_t r_texture_sRGB_skin_diffuse = {0, "r_texture_sRGB_skin_diffuse", "0", "load textures as sRGB"};
136 cvar_t r_texture_sRGB_skin_gloss = {0, "r_texture_sRGB_skin_gloss", "0", "load textures as sRGB"};
137 cvar_t r_texture_sRGB_skin_glow = {0, "r_texture_sRGB_skin_glow", "0", "load textures as sRGB"};
138 cvar_t r_texture_sRGB_skin_reflect = {0, "r_texture_sRGB_skin_reflect", "0", "load textures as sRGB"};
139 cvar_t r_texture_sRGB_cubemap = {0, "r_texture_sRGB_cubemap", "0", "load textures as sRGB"};
140 cvar_t r_texture_sRGB_skybox = {0, "r_texture_sRGB_skybox", "0", "load textures as sRGB"};
141
142 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
143 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
144 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
145
146 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
147 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
148 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
149 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
150 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
151 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
152 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
153 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
154
155 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
156 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
157 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
159 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
160 cvar_t r_glsl_offsetmapping_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)"};
161 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
162 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
163 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)"};
164 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)"};
165 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)"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
171
172 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)"};
173 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
174 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"};
175 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
176 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
177 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
178
179 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
180 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
181 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
182 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
183
184 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
185 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
186 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
187 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
188 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
189 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
190 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
191
192 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
193 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
194 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
195 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)"};
196 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
197 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
198 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
199 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
200 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
201 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
202
203 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"};
204
205 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"};
206
207 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
208
209 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
210 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"};
211 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
212 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
213 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
214 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
215 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)"};
216 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
217 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
218
219 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
220 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"};
221
222 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."};
223
224 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)"};
225
226 extern cvar_t v_glslgamma;
227
228 extern qboolean v_flipped_state;
229
230 static struct r_bloomstate_s
231 {
232         qboolean enabled;
233         qboolean hdr;
234
235         int bloomwidth, bloomheight;
236
237         textype_t texturetype;
238         int viewfbo; // used to check if r_viewfbo cvar has changed
239
240         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
241         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
242         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
243
244         int screentexturewidth, screentextureheight;
245         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
246
247         int bloomtexturewidth, bloomtextureheight;
248         rtexture_t *texture_bloom;
249
250         // arrays for rendering the screen passes
251         float screentexcoord2f[8];
252         float bloomtexcoord2f[8];
253         float offsettexcoord2f[8];
254
255         r_viewport_t viewport;
256 }
257 r_bloomstate;
258
259 r_waterstate_t r_waterstate;
260
261 /// shadow volume bsp struct with automatically growing nodes buffer
262 svbsp_t r_svbsp;
263
264 rtexture_t *r_texture_blanknormalmap;
265 rtexture_t *r_texture_white;
266 rtexture_t *r_texture_grey128;
267 rtexture_t *r_texture_black;
268 rtexture_t *r_texture_notexture;
269 rtexture_t *r_texture_whitecube;
270 rtexture_t *r_texture_normalizationcube;
271 rtexture_t *r_texture_fogattenuation;
272 rtexture_t *r_texture_fogheighttexture;
273 rtexture_t *r_texture_gammaramps;
274 unsigned int r_texture_gammaramps_serial;
275 //rtexture_t *r_texture_fogintensity;
276 rtexture_t *r_texture_reflectcube;
277
278 // TODO: hash lookups?
279 typedef struct cubemapinfo_s
280 {
281         char basename[64];
282         rtexture_t *texture;
283 }
284 cubemapinfo_t;
285
286 int r_texture_numcubemaps;
287 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
288
289 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
290 unsigned int r_numqueries;
291 unsigned int r_maxqueries;
292
293 typedef struct r_qwskincache_s
294 {
295         char name[MAX_QPATH];
296         skinframe_t *skinframe;
297 }
298 r_qwskincache_t;
299
300 static r_qwskincache_t *r_qwskincache;
301 static int r_qwskincache_size;
302
303 /// vertex coordinates for a quad that covers the screen exactly
304 extern const float r_screenvertex3f[12];
305 extern const float r_d3dscreenvertex3f[12];
306 const float r_screenvertex3f[12] =
307 {
308         0, 0, 0,
309         1, 0, 0,
310         1, 1, 0,
311         0, 1, 0
312 };
313 const float r_d3dscreenvertex3f[12] =
314 {
315         0, 1, 0,
316         1, 1, 0,
317         1, 0, 0,
318         0, 0, 0
319 };
320
321 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
322 {
323         int i;
324         for (i = 0;i < verts;i++)
325         {
326                 out[0] = in[0] * r;
327                 out[1] = in[1] * g;
328                 out[2] = in[2] * b;
329                 out[3] = in[3];
330                 in += 4;
331                 out += 4;
332         }
333 }
334
335 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
336 {
337         int i;
338         for (i = 0;i < verts;i++)
339         {
340                 out[0] = r;
341                 out[1] = g;
342                 out[2] = b;
343                 out[3] = a;
344                 out += 4;
345         }
346 }
347
348 // FIXME: move this to client?
349 void FOG_clear(void)
350 {
351         if (gamemode == GAME_NEHAHRA)
352         {
353                 Cvar_Set("gl_fogenable", "0");
354                 Cvar_Set("gl_fogdensity", "0.2");
355                 Cvar_Set("gl_fogred", "0.3");
356                 Cvar_Set("gl_foggreen", "0.3");
357                 Cvar_Set("gl_fogblue", "0.3");
358         }
359         r_refdef.fog_density = 0;
360         r_refdef.fog_red = 0;
361         r_refdef.fog_green = 0;
362         r_refdef.fog_blue = 0;
363         r_refdef.fog_alpha = 1;
364         r_refdef.fog_start = 0;
365         r_refdef.fog_end = 16384;
366         r_refdef.fog_height = 1<<30;
367         r_refdef.fog_fadedepth = 128;
368         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
369 }
370
371 static void R_BuildBlankTextures(void)
372 {
373         unsigned char data[4];
374         data[2] = 128; // normal X
375         data[1] = 128; // normal Y
376         data[0] = 255; // normal Z
377         data[3] = 128; // height
378         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
379         data[0] = 255;
380         data[1] = 255;
381         data[2] = 255;
382         data[3] = 255;
383         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384         data[0] = 128;
385         data[1] = 128;
386         data[2] = 128;
387         data[3] = 255;
388         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
389         data[0] = 0;
390         data[1] = 0;
391         data[2] = 0;
392         data[3] = 255;
393         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
394 }
395
396 static void R_BuildNoTexture(void)
397 {
398         int x, y;
399         unsigned char pix[16][16][4];
400         // this makes a light grey/dark grey checkerboard texture
401         for (y = 0;y < 16;y++)
402         {
403                 for (x = 0;x < 16;x++)
404                 {
405                         if ((y < 8) ^ (x < 8))
406                         {
407                                 pix[y][x][0] = 128;
408                                 pix[y][x][1] = 128;
409                                 pix[y][x][2] = 128;
410                                 pix[y][x][3] = 255;
411                         }
412                         else
413                         {
414                                 pix[y][x][0] = 64;
415                                 pix[y][x][1] = 64;
416                                 pix[y][x][2] = 64;
417                                 pix[y][x][3] = 255;
418                         }
419                 }
420         }
421         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
422 }
423
424 static void R_BuildWhiteCube(void)
425 {
426         unsigned char data[6*1*1*4];
427         memset(data, 255, sizeof(data));
428         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
429 }
430
431 static void R_BuildNormalizationCube(void)
432 {
433         int x, y, side;
434         vec3_t v;
435         vec_t s, t, intensity;
436 #define NORMSIZE 64
437         unsigned char *data;
438         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
439         for (side = 0;side < 6;side++)
440         {
441                 for (y = 0;y < NORMSIZE;y++)
442                 {
443                         for (x = 0;x < NORMSIZE;x++)
444                         {
445                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
446                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
447                                 switch(side)
448                                 {
449                                 default:
450                                 case 0:
451                                         v[0] = 1;
452                                         v[1] = -t;
453                                         v[2] = -s;
454                                         break;
455                                 case 1:
456                                         v[0] = -1;
457                                         v[1] = -t;
458                                         v[2] = s;
459                                         break;
460                                 case 2:
461                                         v[0] = s;
462                                         v[1] = 1;
463                                         v[2] = t;
464                                         break;
465                                 case 3:
466                                         v[0] = s;
467                                         v[1] = -1;
468                                         v[2] = -t;
469                                         break;
470                                 case 4:
471                                         v[0] = s;
472                                         v[1] = -t;
473                                         v[2] = 1;
474                                         break;
475                                 case 5:
476                                         v[0] = -s;
477                                         v[1] = -t;
478                                         v[2] = -1;
479                                         break;
480                                 }
481                                 intensity = 127.0f / sqrt(DotProduct(v, v));
482                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
483                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
484                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
485                                 data[((side*64+y)*64+x)*4+3] = 255;
486                         }
487                 }
488         }
489         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
490         Mem_Free(data);
491 }
492
493 static void R_BuildFogTexture(void)
494 {
495         int x, b;
496 #define FOGWIDTH 256
497         unsigned char data1[FOGWIDTH][4];
498         //unsigned char data2[FOGWIDTH][4];
499         double d, r, alpha;
500
501         r_refdef.fogmasktable_start = r_refdef.fog_start;
502         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
503         r_refdef.fogmasktable_range = r_refdef.fogrange;
504         r_refdef.fogmasktable_density = r_refdef.fog_density;
505
506         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
507         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
508         {
509                 d = (x * r - r_refdef.fogmasktable_start);
510                 if(developer_extra.integer)
511                         Con_DPrintf("%f ", d);
512                 d = max(0, d);
513                 if (r_fog_exp2.integer)
514                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
515                 else
516                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
517                 if(developer_extra.integer)
518                         Con_DPrintf(" : %f ", alpha);
519                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
520                 if(developer_extra.integer)
521                         Con_DPrintf(" = %f\n", alpha);
522                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
523         }
524
525         for (x = 0;x < FOGWIDTH;x++)
526         {
527                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
528                 data1[x][0] = b;
529                 data1[x][1] = b;
530                 data1[x][2] = b;
531                 data1[x][3] = 255;
532                 //data2[x][0] = 255 - b;
533                 //data2[x][1] = 255 - b;
534                 //data2[x][2] = 255 - b;
535                 //data2[x][3] = 255;
536         }
537         if (r_texture_fogattenuation)
538         {
539                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
540                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541         }
542         else
543         {
544                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
545                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
546         }
547 }
548
549 static void R_BuildFogHeightTexture(void)
550 {
551         unsigned char *inpixels;
552         int size;
553         int x;
554         int y;
555         int j;
556         float c[4];
557         float f;
558         inpixels = NULL;
559         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
560         if (r_refdef.fogheighttexturename[0])
561                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
562         if (!inpixels)
563         {
564                 r_refdef.fog_height_tablesize = 0;
565                 if (r_texture_fogheighttexture)
566                         R_FreeTexture(r_texture_fogheighttexture);
567                 r_texture_fogheighttexture = NULL;
568                 if (r_refdef.fog_height_table2d)
569                         Mem_Free(r_refdef.fog_height_table2d);
570                 r_refdef.fog_height_table2d = NULL;
571                 if (r_refdef.fog_height_table1d)
572                         Mem_Free(r_refdef.fog_height_table1d);
573                 r_refdef.fog_height_table1d = NULL;
574                 return;
575         }
576         size = image_width;
577         r_refdef.fog_height_tablesize = size;
578         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
579         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
580         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
581         Mem_Free(inpixels);
582         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
583         // average fog color table accounting for every fog layer between a point
584         // and the camera.  (Note: attenuation is handled separately!)
585         for (y = 0;y < size;y++)
586         {
587                 for (x = 0;x < size;x++)
588                 {
589                         Vector4Clear(c);
590                         f = 0;
591                         if (x < y)
592                         {
593                                 for (j = x;j <= y;j++)
594                                 {
595                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
596                                         f++;
597                                 }
598                         }
599                         else
600                         {
601                                 for (j = x;j >= y;j--)
602                                 {
603                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
604                                         f++;
605                                 }
606                         }
607                         f = 1.0f / f;
608                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
609                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
610                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
611                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
612                 }
613         }
614         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
615 }
616
617 //=======================================================================================================================================================
618
619 static const char *builtinshaderstring =
620 #include "shader_glsl.h"
621 ;
622
623 const char *builtinhlslshaderstring =
624 #include "shader_hlsl.h"
625 ;
626
627 char *glslshaderstring = NULL;
628 char *hlslshaderstring = NULL;
629
630 //=======================================================================================================================================================
631
632 typedef struct shaderpermutationinfo_s
633 {
634         const char *pretext;
635         const char *name;
636 }
637 shaderpermutationinfo_t;
638
639 typedef struct shadermodeinfo_s
640 {
641         const char *vertexfilename;
642         const char *geometryfilename;
643         const char *fragmentfilename;
644         const char *pretext;
645         const char *name;
646 }
647 shadermodeinfo_t;
648
649 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
650 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
651 {
652         {"#define USEDIFFUSE\n", " diffuse"},
653         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
654         {"#define USEVIEWTINT\n", " viewtint"},
655         {"#define USECOLORMAPPING\n", " colormapping"},
656         {"#define USESATURATION\n", " saturation"},
657         {"#define USEFOGINSIDE\n", " foginside"},
658         {"#define USEFOGOUTSIDE\n", " fogoutside"},
659         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
660         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
661         {"#define USEGAMMARAMPS\n", " gammaramps"},
662         {"#define USECUBEFILTER\n", " cubefilter"},
663         {"#define USEGLOW\n", " glow"},
664         {"#define USEBLOOM\n", " bloom"},
665         {"#define USESPECULAR\n", " specular"},
666         {"#define USEPOSTPROCESSING\n", " postprocessing"},
667         {"#define USEREFLECTION\n", " reflection"},
668         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
669         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
670         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
671         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
672         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
673         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
674         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
675         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
676         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
677         {"#define USEALPHAKILL\n", " alphakill"},
678         {"#define USEREFLECTCUBE\n", " reflectcube"},
679         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
680         {"#define USEBOUNCEGRID\n", " bouncegrid"},
681         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
682 };
683
684 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
685 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
686 {
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
689         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
703 };
704
705 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
706 {
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
723 };
724
725 struct r_glsl_permutation_s;
726 typedef struct r_glsl_permutation_s
727 {
728         /// hash lookup data
729         struct r_glsl_permutation_s *hashnext;
730         unsigned int mode;
731         unsigned int permutation;
732
733         /// indicates if we have tried compiling this permutation already
734         qboolean compiled;
735         /// 0 if compilation failed
736         int program;
737         // texture units assigned to each detected uniform
738         int tex_Texture_First;
739         int tex_Texture_Second;
740         int tex_Texture_GammaRamps;
741         int tex_Texture_Normal;
742         int tex_Texture_Color;
743         int tex_Texture_Gloss;
744         int tex_Texture_Glow;
745         int tex_Texture_SecondaryNormal;
746         int tex_Texture_SecondaryColor;
747         int tex_Texture_SecondaryGloss;
748         int tex_Texture_SecondaryGlow;
749         int tex_Texture_Pants;
750         int tex_Texture_Shirt;
751         int tex_Texture_FogHeightTexture;
752         int tex_Texture_FogMask;
753         int tex_Texture_Lightmap;
754         int tex_Texture_Deluxemap;
755         int tex_Texture_Attenuation;
756         int tex_Texture_Cube;
757         int tex_Texture_Refraction;
758         int tex_Texture_Reflection;
759         int tex_Texture_ShadowMap2D;
760         int tex_Texture_CubeProjection;
761         int tex_Texture_ScreenDepth;
762         int tex_Texture_ScreenNormalMap;
763         int tex_Texture_ScreenDiffuse;
764         int tex_Texture_ScreenSpecular;
765         int tex_Texture_ReflectMask;
766         int tex_Texture_ReflectCube;
767         int tex_Texture_BounceGrid;
768         /// locations of detected uniforms in program object, or -1 if not found
769         int loc_Texture_First;
770         int loc_Texture_Second;
771         int loc_Texture_GammaRamps;
772         int loc_Texture_Normal;
773         int loc_Texture_Color;
774         int loc_Texture_Gloss;
775         int loc_Texture_Glow;
776         int loc_Texture_SecondaryNormal;
777         int loc_Texture_SecondaryColor;
778         int loc_Texture_SecondaryGloss;
779         int loc_Texture_SecondaryGlow;
780         int loc_Texture_Pants;
781         int loc_Texture_Shirt;
782         int loc_Texture_FogHeightTexture;
783         int loc_Texture_FogMask;
784         int loc_Texture_Lightmap;
785         int loc_Texture_Deluxemap;
786         int loc_Texture_Attenuation;
787         int loc_Texture_Cube;
788         int loc_Texture_Refraction;
789         int loc_Texture_Reflection;
790         int loc_Texture_ShadowMap2D;
791         int loc_Texture_CubeProjection;
792         int loc_Texture_ScreenDepth;
793         int loc_Texture_ScreenNormalMap;
794         int loc_Texture_ScreenDiffuse;
795         int loc_Texture_ScreenSpecular;
796         int loc_Texture_ReflectMask;
797         int loc_Texture_ReflectCube;
798         int loc_Texture_BounceGrid;
799         int loc_Alpha;
800         int loc_BloomBlur_Parameters;
801         int loc_ClientTime;
802         int loc_Color_Ambient;
803         int loc_Color_Diffuse;
804         int loc_Color_Specular;
805         int loc_Color_Glow;
806         int loc_Color_Pants;
807         int loc_Color_Shirt;
808         int loc_DeferredColor_Ambient;
809         int loc_DeferredColor_Diffuse;
810         int loc_DeferredColor_Specular;
811         int loc_DeferredMod_Diffuse;
812         int loc_DeferredMod_Specular;
813         int loc_DistortScaleRefractReflect;
814         int loc_EyePosition;
815         int loc_FogColor;
816         int loc_FogHeightFade;
817         int loc_FogPlane;
818         int loc_FogPlaneViewDist;
819         int loc_FogRangeRecip;
820         int loc_LightColor;
821         int loc_LightDir;
822         int loc_LightPosition;
823         int loc_OffsetMapping_ScaleSteps;
824         int loc_PixelSize;
825         int loc_ReflectColor;
826         int loc_ReflectFactor;
827         int loc_ReflectOffset;
828         int loc_RefractColor;
829         int loc_Saturation;
830         int loc_ScreenCenterRefractReflect;
831         int loc_ScreenScaleRefractReflect;
832         int loc_ScreenToDepth;
833         int loc_ShadowMap_Parameters;
834         int loc_ShadowMap_TextureScale;
835         int loc_SpecularPower;
836         int loc_UserVec1;
837         int loc_UserVec2;
838         int loc_UserVec3;
839         int loc_UserVec4;
840         int loc_ViewTintColor;
841         int loc_ViewToLight;
842         int loc_ModelToLight;
843         int loc_TexMatrix;
844         int loc_BackgroundTexMatrix;
845         int loc_ModelViewProjectionMatrix;
846         int loc_ModelViewMatrix;
847         int loc_PixelToScreenTexCoord;
848         int loc_ModelToReflectCube;
849         int loc_ShadowMapMatrix;
850         int loc_BloomColorSubtract;
851         int loc_NormalmapScrollBlend;
852         int loc_BounceGridMatrix;
853         int loc_BounceGridIntensity;
854 }
855 r_glsl_permutation_t;
856
857 #define SHADERPERMUTATION_HASHSIZE 256
858
859
860 // non-degradable "lightweight" shader parameters to keep the permutations simpler
861 // these can NOT degrade! only use for simple stuff
862 enum
863 {
864         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
865         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
866         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
867         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
868         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
869         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
870         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
871 };
872 #define SHADERSTATICPARMS_COUNT 7
873
874 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
875 static int shaderstaticparms_count = 0;
876
877 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
878 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
879 qboolean R_CompileShader_CheckStaticParms(void)
880 {
881         static int r_compileshader_staticparms_save[1];
882         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
883         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
884
885         // detect all
886         if (r_glsl_saturation_redcompensate.integer)
887                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
888         if (r_glsl_vertextextureblend_usebothalphas.integer)
889                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
890         if (r_shadow_glossexact.integer)
891                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
892         if (r_glsl_postprocess.integer)
893         {
894                 if (r_glsl_postprocess_uservec1_enable.integer)
895                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
896                 if (r_glsl_postprocess_uservec2_enable.integer)
897                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
898                 if (r_glsl_postprocess_uservec3_enable.integer)
899                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
900                 if (r_glsl_postprocess_uservec4_enable.integer)
901                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
902         }
903         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
904 }
905
906 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
907         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
908                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
909         else \
910                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
911 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
912 {
913         shaderstaticparms_count = 0;
914
915         // emit all
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
923 }
924
925 /// information about each possible shader permutation
926 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
927 /// currently selected permutation
928 r_glsl_permutation_t *r_glsl_permutation;
929 /// storage for permutations linked in the hash table
930 memexpandablearray_t r_glsl_permutationarray;
931
932 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
933 {
934         //unsigned int hashdepth = 0;
935         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
936         r_glsl_permutation_t *p;
937         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
938         {
939                 if (p->mode == mode && p->permutation == permutation)
940                 {
941                         //if (hashdepth > 10)
942                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
943                         return p;
944                 }
945                 //hashdepth++;
946         }
947         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
948         p->mode = mode;
949         p->permutation = permutation;
950         p->hashnext = r_glsl_permutationhash[mode][hashindex];
951         r_glsl_permutationhash[mode][hashindex] = p;
952         //if (hashdepth > 10)
953         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
954         return p;
955 }
956
957 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
958 {
959         char *shaderstring;
960         if (!filename || !filename[0])
961                 return NULL;
962         if (!strcmp(filename, "glsl/default.glsl"))
963         {
964                 if (!glslshaderstring)
965                 {
966                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
967                         if (glslshaderstring)
968                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
969                         else
970                                 glslshaderstring = (char *)builtinshaderstring;
971                 }
972                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
973                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
974                 return shaderstring;
975         }
976         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
977         if (shaderstring)
978         {
979                 if (printfromdisknotice)
980                         Con_DPrintf("from disk %s... ", filename);
981                 return shaderstring;
982         }
983         return shaderstring;
984 }
985
986 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
987 {
988         int i;
989         int sampler;
990         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
991         char *vertexstring, *geometrystring, *fragmentstring;
992         char permutationname[256];
993         int vertstrings_count = 0;
994         int geomstrings_count = 0;
995         int fragstrings_count = 0;
996         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
997         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
998         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
999
1000         if (p->compiled)
1001                 return;
1002         p->compiled = true;
1003         p->program = 0;
1004
1005         permutationname[0] = 0;
1006         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1007         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1008         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1009
1010         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1011
1012         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1013         if(vid.support.gl20shaders130)
1014         {
1015                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1016                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1017                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1018                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1019                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1020                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1021         }
1022
1023         // the first pretext is which type of shader to compile as
1024         // (later these will all be bound together as a program object)
1025         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1026         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1027         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1028
1029         // the second pretext is the mode (for example a light source)
1030         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1031         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1032         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1033         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1034
1035         // now add all the permutation pretexts
1036         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1037         {
1038                 if (permutation & (1<<i))
1039                 {
1040                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1041                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1042                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1043                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1044                 }
1045                 else
1046                 {
1047                         // keep line numbers correct
1048                         vertstrings_list[vertstrings_count++] = "\n";
1049                         geomstrings_list[geomstrings_count++] = "\n";
1050                         fragstrings_list[fragstrings_count++] = "\n";
1051                 }
1052         }
1053
1054         // add static parms
1055         R_CompileShader_AddStaticParms(mode, permutation);
1056         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1057         vertstrings_count += shaderstaticparms_count;
1058         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1059         geomstrings_count += shaderstaticparms_count;
1060         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1061         fragstrings_count += shaderstaticparms_count;
1062
1063         // now append the shader text itself
1064         vertstrings_list[vertstrings_count++] = vertexstring;
1065         geomstrings_list[geomstrings_count++] = geometrystring;
1066         fragstrings_list[fragstrings_count++] = fragmentstring;
1067
1068         // if any sources were NULL, clear the respective list
1069         if (!vertexstring)
1070                 vertstrings_count = 0;
1071         if (!geometrystring)
1072                 geomstrings_count = 0;
1073         if (!fragmentstring)
1074                 fragstrings_count = 0;
1075
1076         // compile the shader program
1077         if (vertstrings_count + geomstrings_count + fragstrings_count)
1078                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1079         if (p->program)
1080         {
1081                 CHECKGLERROR
1082                 qglUseProgram(p->program);CHECKGLERROR
1083                 // look up all the uniform variable names we care about, so we don't
1084                 // have to look them up every time we set them
1085
1086                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1087                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1088                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1089                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1090                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1091                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1092                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1093                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1094                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1095                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1096                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1097                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1098                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1099                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1100                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1101                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1102                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1103                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1104                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1105                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1106                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1107                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1108                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1109                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1110                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1111                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1112                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1113                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1114                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1115                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1116                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1117                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1118                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1119                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1120                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1121                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1122                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1123                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1124                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1125                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1126                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1127                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1128                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1129                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1130                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1131                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1132                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1133                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1134                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1135                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1136                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1137                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1138                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1139                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1140                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1141                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1142                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1143                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1144                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1145                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1146                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1147                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1148                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1149                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1150                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1151                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1152                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1153                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1154                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1155                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1156                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1157                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1158                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1159                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1160                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1161                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1162                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1163                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1164                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1165                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1166                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1167                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1168                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1169                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1170                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1171                 // initialize the samplers to refer to the texture units we use
1172                 p->tex_Texture_First = -1;
1173                 p->tex_Texture_Second = -1;
1174                 p->tex_Texture_GammaRamps = -1;
1175                 p->tex_Texture_Normal = -1;
1176                 p->tex_Texture_Color = -1;
1177                 p->tex_Texture_Gloss = -1;
1178                 p->tex_Texture_Glow = -1;
1179                 p->tex_Texture_SecondaryNormal = -1;
1180                 p->tex_Texture_SecondaryColor = -1;
1181                 p->tex_Texture_SecondaryGloss = -1;
1182                 p->tex_Texture_SecondaryGlow = -1;
1183                 p->tex_Texture_Pants = -1;
1184                 p->tex_Texture_Shirt = -1;
1185                 p->tex_Texture_FogHeightTexture = -1;
1186                 p->tex_Texture_FogMask = -1;
1187                 p->tex_Texture_Lightmap = -1;
1188                 p->tex_Texture_Deluxemap = -1;
1189                 p->tex_Texture_Attenuation = -1;
1190                 p->tex_Texture_Cube = -1;
1191                 p->tex_Texture_Refraction = -1;
1192                 p->tex_Texture_Reflection = -1;
1193                 p->tex_Texture_ShadowMap2D = -1;
1194                 p->tex_Texture_CubeProjection = -1;
1195                 p->tex_Texture_ScreenDepth = -1;
1196                 p->tex_Texture_ScreenNormalMap = -1;
1197                 p->tex_Texture_ScreenDiffuse = -1;
1198                 p->tex_Texture_ScreenSpecular = -1;
1199                 p->tex_Texture_ReflectMask = -1;
1200                 p->tex_Texture_ReflectCube = -1;
1201                 p->tex_Texture_BounceGrid = -1;
1202                 sampler = 0;
1203                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1204                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1205                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1206                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1207                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1208                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1209                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1210                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1211                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1212                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1213                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1214                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1215                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1216                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1217                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1218                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1219                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1220                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1221                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1222                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1223                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1224                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1225                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1226                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1227                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1228                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1229                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1230                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1231                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1232                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1233                 CHECKGLERROR
1234                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1235         }
1236         else
1237                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1238
1239         // free the strings
1240         if (vertexstring)
1241                 Mem_Free(vertexstring);
1242         if (geometrystring)
1243                 Mem_Free(geometrystring);
1244         if (fragmentstring)
1245                 Mem_Free(fragmentstring);
1246 }
1247
1248 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1249 {
1250         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1251         if (r_glsl_permutation != perm)
1252         {
1253                 r_glsl_permutation = perm;
1254                 if (!r_glsl_permutation->program)
1255                 {
1256                         if (!r_glsl_permutation->compiled)
1257                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1258                         if (!r_glsl_permutation->program)
1259                         {
1260                                 // remove features until we find a valid permutation
1261                                 int i;
1262                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1263                                 {
1264                                         // reduce i more quickly whenever it would not remove any bits
1265                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1266                                         if (!(permutation & j))
1267                                                 continue;
1268                                         permutation -= j;
1269                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1270                                         if (!r_glsl_permutation->compiled)
1271                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1272                                         if (r_glsl_permutation->program)
1273                                                 break;
1274                                 }
1275                                 if (i >= SHADERPERMUTATION_COUNT)
1276                                 {
1277                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1278                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1279                                         qglUseProgram(0);CHECKGLERROR
1280                                         return; // no bit left to clear, entire mode is broken
1281                                 }
1282                         }
1283                 }
1284                 CHECKGLERROR
1285                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1286         }
1287         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1288         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1289         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1290 }
1291
1292 #ifdef SUPPORTD3D
1293
1294 #ifdef SUPPORTD3D
1295 #include <d3d9.h>
1296 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1297 extern D3DCAPS9 vid_d3d9caps;
1298 #endif
1299
1300 struct r_hlsl_permutation_s;
1301 typedef struct r_hlsl_permutation_s
1302 {
1303         /// hash lookup data
1304         struct r_hlsl_permutation_s *hashnext;
1305         unsigned int mode;
1306         unsigned int permutation;
1307
1308         /// indicates if we have tried compiling this permutation already
1309         qboolean compiled;
1310         /// NULL if compilation failed
1311         IDirect3DVertexShader9 *vertexshader;
1312         IDirect3DPixelShader9 *pixelshader;
1313 }
1314 r_hlsl_permutation_t;
1315
1316 typedef enum D3DVSREGISTER_e
1317 {
1318         D3DVSREGISTER_TexMatrix = 0, // float4x4
1319         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1320         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1321         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1322         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1323         D3DVSREGISTER_ModelToLight = 20, // float4x4
1324         D3DVSREGISTER_EyePosition = 24,
1325         D3DVSREGISTER_FogPlane = 25,
1326         D3DVSREGISTER_LightDir = 26,
1327         D3DVSREGISTER_LightPosition = 27,
1328 }
1329 D3DVSREGISTER_t;
1330
1331 typedef enum D3DPSREGISTER_e
1332 {
1333         D3DPSREGISTER_Alpha = 0,
1334         D3DPSREGISTER_BloomBlur_Parameters = 1,
1335         D3DPSREGISTER_ClientTime = 2,
1336         D3DPSREGISTER_Color_Ambient = 3,
1337         D3DPSREGISTER_Color_Diffuse = 4,
1338         D3DPSREGISTER_Color_Specular = 5,
1339         D3DPSREGISTER_Color_Glow = 6,
1340         D3DPSREGISTER_Color_Pants = 7,
1341         D3DPSREGISTER_Color_Shirt = 8,
1342         D3DPSREGISTER_DeferredColor_Ambient = 9,
1343         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1344         D3DPSREGISTER_DeferredColor_Specular = 11,
1345         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1346         D3DPSREGISTER_DeferredMod_Specular = 13,
1347         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1348         D3DPSREGISTER_EyePosition = 15, // unused
1349         D3DPSREGISTER_FogColor = 16,
1350         D3DPSREGISTER_FogHeightFade = 17,
1351         D3DPSREGISTER_FogPlane = 18,
1352         D3DPSREGISTER_FogPlaneViewDist = 19,
1353         D3DPSREGISTER_FogRangeRecip = 20,
1354         D3DPSREGISTER_LightColor = 21,
1355         D3DPSREGISTER_LightDir = 22, // unused
1356         D3DPSREGISTER_LightPosition = 23,
1357         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1358         D3DPSREGISTER_PixelSize = 25,
1359         D3DPSREGISTER_ReflectColor = 26,
1360         D3DPSREGISTER_ReflectFactor = 27,
1361         D3DPSREGISTER_ReflectOffset = 28,
1362         D3DPSREGISTER_RefractColor = 29,
1363         D3DPSREGISTER_Saturation = 30,
1364         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1365         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1366         D3DPSREGISTER_ScreenToDepth = 33,
1367         D3DPSREGISTER_ShadowMap_Parameters = 34,
1368         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1369         D3DPSREGISTER_SpecularPower = 36,
1370         D3DPSREGISTER_UserVec1 = 37,
1371         D3DPSREGISTER_UserVec2 = 38,
1372         D3DPSREGISTER_UserVec3 = 39,
1373         D3DPSREGISTER_UserVec4 = 40,
1374         D3DPSREGISTER_ViewTintColor = 41,
1375         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1376         D3DPSREGISTER_BloomColorSubtract = 43,
1377         D3DPSREGISTER_ViewToLight = 44, // float4x4
1378         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1379         D3DPSREGISTER_NormalmapScrollBlend = 52,
1380         // next at 53
1381 }
1382 D3DPSREGISTER_t;
1383
1384 /// information about each possible shader permutation
1385 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1386 /// currently selected permutation
1387 r_hlsl_permutation_t *r_hlsl_permutation;
1388 /// storage for permutations linked in the hash table
1389 memexpandablearray_t r_hlsl_permutationarray;
1390
1391 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1392 {
1393         //unsigned int hashdepth = 0;
1394         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1395         r_hlsl_permutation_t *p;
1396         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1397         {
1398                 if (p->mode == mode && p->permutation == permutation)
1399                 {
1400                         //if (hashdepth > 10)
1401                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1402                         return p;
1403                 }
1404                 //hashdepth++;
1405         }
1406         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1407         p->mode = mode;
1408         p->permutation = permutation;
1409         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1410         r_hlsl_permutationhash[mode][hashindex] = p;
1411         //if (hashdepth > 10)
1412         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1413         return p;
1414 }
1415
1416 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1417 {
1418         char *shaderstring;
1419         if (!filename || !filename[0])
1420                 return NULL;
1421         if (!strcmp(filename, "hlsl/default.hlsl"))
1422         {
1423                 if (!hlslshaderstring)
1424                 {
1425                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1426                         if (hlslshaderstring)
1427                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1428                         else
1429                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1430                 }
1431                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1432                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1433                 return shaderstring;
1434         }
1435         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1436         if (shaderstring)
1437         {
1438                 if (printfromdisknotice)
1439                         Con_DPrintf("from disk %s... ", filename);
1440                 return shaderstring;
1441         }
1442         return shaderstring;
1443 }
1444
1445 #include <d3dx9.h>
1446 //#include <d3dx9shader.h>
1447 //#include <d3dx9mesh.h>
1448
1449 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1450 {
1451         DWORD *vsbin = NULL;
1452         DWORD *psbin = NULL;
1453         fs_offset_t vsbinsize;
1454         fs_offset_t psbinsize;
1455 //      IDirect3DVertexShader9 *vs = NULL;
1456 //      IDirect3DPixelShader9 *ps = NULL;
1457         ID3DXBuffer *vslog = NULL;
1458         ID3DXBuffer *vsbuffer = NULL;
1459         ID3DXConstantTable *vsconstanttable = NULL;
1460         ID3DXBuffer *pslog = NULL;
1461         ID3DXBuffer *psbuffer = NULL;
1462         ID3DXConstantTable *psconstanttable = NULL;
1463         int vsresult = 0;
1464         int psresult = 0;
1465         char temp[MAX_INPUTLINE];
1466         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1467         qboolean debugshader = gl_paranoid.integer != 0;
1468         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1469         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1470         if (!debugshader)
1471         {
1472                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1473                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1474         }
1475         if ((!vsbin && vertstring) || (!psbin && fragstring))
1476         {
1477                 const char* dllnames_d3dx9 [] =
1478                 {
1479                         "d3dx9_43.dll",
1480                         "d3dx9_42.dll",
1481                         "d3dx9_41.dll",
1482                         "d3dx9_40.dll",
1483                         "d3dx9_39.dll",
1484                         "d3dx9_38.dll",
1485                         "d3dx9_37.dll",
1486                         "d3dx9_36.dll",
1487                         "d3dx9_35.dll",
1488                         "d3dx9_34.dll",
1489                         "d3dx9_33.dll",
1490                         "d3dx9_32.dll",
1491                         "d3dx9_31.dll",
1492                         "d3dx9_30.dll",
1493                         "d3dx9_29.dll",
1494                         "d3dx9_28.dll",
1495                         "d3dx9_27.dll",
1496                         "d3dx9_26.dll",
1497                         "d3dx9_25.dll",
1498                         "d3dx9_24.dll",
1499                         NULL
1500                 };
1501                 dllhandle_t d3dx9_dll = NULL;
1502                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1503                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1504                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1505                 dllfunction_t d3dx9_dllfuncs[] =
1506                 {
1507                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1508                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1509                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1510                         {NULL, NULL}
1511                 };
1512                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1513                 {
1514                         DWORD shaderflags = 0;
1515                         if (debugshader)
1516                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1517                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1518                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1519                         if (vertstring && vertstring[0])
1520                         {
1521                                 if (debugshader)
1522                                 {
1523 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1524 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1525                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1526                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1527                                 }
1528                                 else
1529                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1530                                 if (vsbuffer)
1531                                 {
1532                                         vsbinsize = vsbuffer->GetBufferSize();
1533                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1534                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1535                                         vsbuffer->Release();
1536                                 }
1537                                 if (vslog)
1538                                 {
1539                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1540                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1541                                         vslog->Release();
1542                                 }
1543                         }
1544                         if (fragstring && fragstring[0])
1545                         {
1546                                 if (debugshader)
1547                                 {
1548 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1549 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1550                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1551                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1552                                 }
1553                                 else
1554                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1555                                 if (psbuffer)
1556                                 {
1557                                         psbinsize = psbuffer->GetBufferSize();
1558                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1559                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1560                                         psbuffer->Release();
1561                                 }
1562                                 if (pslog)
1563                                 {
1564                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1565                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1566                                         pslog->Release();
1567                                 }
1568                         }
1569                         Sys_UnloadLibrary(&d3dx9_dll);
1570                 }
1571                 else
1572                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1573         }
1574         if (vsbin && psbin)
1575         {
1576                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1577                 if (FAILED(vsresult))
1578                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1579                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1580                 if (FAILED(psresult))
1581                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1582         }
1583         // free the shader data
1584         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1585         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1586 }
1587
1588 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1589 {
1590         int i;
1591         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1592         int vertstring_length = 0;
1593         int geomstring_length = 0;
1594         int fragstring_length = 0;
1595         char *t;
1596         char *vertexstring, *geometrystring, *fragmentstring;
1597         char *vertstring, *geomstring, *fragstring;
1598         char permutationname[256];
1599         char cachename[256];
1600         int vertstrings_count = 0;
1601         int geomstrings_count = 0;
1602         int fragstrings_count = 0;
1603         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1604         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1605         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1606
1607         if (p->compiled)
1608                 return;
1609         p->compiled = true;
1610         p->vertexshader = NULL;
1611         p->pixelshader = NULL;
1612
1613         permutationname[0] = 0;
1614         cachename[0] = 0;
1615         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1616         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1617         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1618
1619         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1620         strlcat(cachename, "hlsl/", sizeof(cachename));
1621
1622         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1623         vertstrings_count = 0;
1624         geomstrings_count = 0;
1625         fragstrings_count = 0;
1626         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1627         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1628         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1629
1630         // the first pretext is which type of shader to compile as
1631         // (later these will all be bound together as a program object)
1632         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1633         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1634         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1635
1636         // the second pretext is the mode (for example a light source)
1637         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1638         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1639         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1640         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1641         strlcat(cachename, modeinfo->name, sizeof(cachename));
1642
1643         // now add all the permutation pretexts
1644         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1645         {
1646                 if (permutation & (1<<i))
1647                 {
1648                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1649                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1650                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1651                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1652                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1653                 }
1654                 else
1655                 {
1656                         // keep line numbers correct
1657                         vertstrings_list[vertstrings_count++] = "\n";
1658                         geomstrings_list[geomstrings_count++] = "\n";
1659                         fragstrings_list[fragstrings_count++] = "\n";
1660                 }
1661         }
1662
1663         // add static parms
1664         R_CompileShader_AddStaticParms(mode, permutation);
1665         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1666         vertstrings_count += shaderstaticparms_count;
1667         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1668         geomstrings_count += shaderstaticparms_count;
1669         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1670         fragstrings_count += shaderstaticparms_count;
1671
1672         // replace spaces in the cachename with _ characters
1673         for (i = 0;cachename[i];i++)
1674                 if (cachename[i] == ' ')
1675                         cachename[i] = '_';
1676
1677         // now append the shader text itself
1678         vertstrings_list[vertstrings_count++] = vertexstring;
1679         geomstrings_list[geomstrings_count++] = geometrystring;
1680         fragstrings_list[fragstrings_count++] = fragmentstring;
1681
1682         // if any sources were NULL, clear the respective list
1683         if (!vertexstring)
1684                 vertstrings_count = 0;
1685         if (!geometrystring)
1686                 geomstrings_count = 0;
1687         if (!fragmentstring)
1688                 fragstrings_count = 0;
1689
1690         vertstring_length = 0;
1691         for (i = 0;i < vertstrings_count;i++)
1692                 vertstring_length += strlen(vertstrings_list[i]);
1693         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1694         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1695                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1696
1697         geomstring_length = 0;
1698         for (i = 0;i < geomstrings_count;i++)
1699                 geomstring_length += strlen(geomstrings_list[i]);
1700         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1701         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1702                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1703
1704         fragstring_length = 0;
1705         for (i = 0;i < fragstrings_count;i++)
1706                 fragstring_length += strlen(fragstrings_list[i]);
1707         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1708         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1709                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1710
1711         // try to load the cached shader, or generate one
1712         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1713
1714         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1715                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1716         else
1717                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1718
1719         // free the strings
1720         if (vertstring)
1721                 Mem_Free(vertstring);
1722         if (geomstring)
1723                 Mem_Free(geomstring);
1724         if (fragstring)
1725                 Mem_Free(fragstring);
1726         if (vertexstring)
1727                 Mem_Free(vertexstring);
1728         if (geometrystring)
1729                 Mem_Free(geometrystring);
1730         if (fragmentstring)
1731                 Mem_Free(fragmentstring);
1732 }
1733
1734 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1735 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1736 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);}
1737 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);}
1738 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);}
1739 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);}
1740
1741 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1742 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1743 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);}
1744 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);}
1745 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);}
1746 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);}
1747
1748 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1749 {
1750         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1751         if (r_hlsl_permutation != perm)
1752         {
1753                 r_hlsl_permutation = perm;
1754                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1755                 {
1756                         if (!r_hlsl_permutation->compiled)
1757                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1758                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1759                         {
1760                                 // remove features until we find a valid permutation
1761                                 int i;
1762                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1763                                 {
1764                                         // reduce i more quickly whenever it would not remove any bits
1765                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1766                                         if (!(permutation & j))
1767                                                 continue;
1768                                         permutation -= j;
1769                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1770                                         if (!r_hlsl_permutation->compiled)
1771                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1772                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1773                                                 break;
1774                                 }
1775                                 if (i >= SHADERPERMUTATION_COUNT)
1776                                 {
1777                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1778                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1779                                         return; // no bit left to clear, entire mode is broken
1780                                 }
1781                         }
1782                 }
1783                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1784                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1785         }
1786         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1787         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1788         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1789 }
1790 #endif
1791
1792 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1793 {
1794         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1795         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1796         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1797         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1798 }
1799
1800 void R_GLSL_Restart_f(void)
1801 {
1802         unsigned int i, limit;
1803         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1804                 Mem_Free(glslshaderstring);
1805         glslshaderstring = NULL;
1806         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1807                 Mem_Free(hlslshaderstring);
1808         hlslshaderstring = NULL;
1809         switch(vid.renderpath)
1810         {
1811         case RENDERPATH_D3D9:
1812 #ifdef SUPPORTD3D
1813                 {
1814                         r_hlsl_permutation_t *p;
1815                         r_hlsl_permutation = NULL;
1816                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1817                         for (i = 0;i < limit;i++)
1818                         {
1819                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1820                                 {
1821                                         if (p->vertexshader)
1822                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1823                                         if (p->pixelshader)
1824                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1825                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1826                                 }
1827                         }
1828                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1829                 }
1830 #endif
1831                 break;
1832         case RENDERPATH_D3D10:
1833                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1834                 break;
1835         case RENDERPATH_D3D11:
1836                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1837                 break;
1838         case RENDERPATH_GL20:
1839         case RENDERPATH_GLES2:
1840                 {
1841                         r_glsl_permutation_t *p;
1842                         r_glsl_permutation = NULL;
1843                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1844                         for (i = 0;i < limit;i++)
1845                         {
1846                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1847                                 {
1848                                         GL_Backend_FreeProgram(p->program);
1849                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1850                                 }
1851                         }
1852                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1853                 }
1854                 break;
1855         case RENDERPATH_GL13:
1856         case RENDERPATH_GL11:
1857                 break;
1858         case RENDERPATH_SOFT:
1859                 break;
1860         }
1861 }
1862
1863 void R_GLSL_DumpShader_f(void)
1864 {
1865         int i;
1866         qfile_t *file;
1867
1868         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1869         if (file)
1870         {
1871                 FS_Print(file, "/* The engine may define the following macros:\n");
1872                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1873                 for (i = 0;i < SHADERMODE_COUNT;i++)
1874                         FS_Print(file, glslshadermodeinfo[i].pretext);
1875                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1876                         FS_Print(file, shaderpermutationinfo[i].pretext);
1877                 FS_Print(file, "*/\n");
1878                 FS_Print(file, builtinshaderstring);
1879                 FS_Close(file);
1880                 Con_Printf("glsl/default.glsl written\n");
1881         }
1882         else
1883                 Con_Printf("failed to write to glsl/default.glsl\n");
1884
1885         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1886         if (file)
1887         {
1888                 FS_Print(file, "/* The engine may define the following macros:\n");
1889                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1890                 for (i = 0;i < SHADERMODE_COUNT;i++)
1891                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1892                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1893                         FS_Print(file, shaderpermutationinfo[i].pretext);
1894                 FS_Print(file, "*/\n");
1895                 FS_Print(file, builtinhlslshaderstring);
1896                 FS_Close(file);
1897                 Con_Printf("hlsl/default.hlsl written\n");
1898         }
1899         else
1900                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1901 }
1902
1903 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1904 {
1905         if (!second)
1906                 texturemode = GL_MODULATE;
1907         switch (vid.renderpath)
1908         {
1909         case RENDERPATH_D3D9:
1910 #ifdef SUPPORTD3D
1911                 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))));
1912                 R_Mesh_TexBind(GL20TU_FIRST , first );
1913                 R_Mesh_TexBind(GL20TU_SECOND, second);
1914 #endif
1915                 break;
1916         case RENDERPATH_D3D10:
1917                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1918                 break;
1919         case RENDERPATH_D3D11:
1920                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1921                 break;
1922         case RENDERPATH_GL20:
1923         case RENDERPATH_GLES2:
1924                 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))));
1925                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1926                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1927                 break;
1928         case RENDERPATH_GL13:
1929                 R_Mesh_TexBind(0, first );
1930                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1931                 R_Mesh_TexBind(1, second);
1932                 if (second)
1933                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1934                 break;
1935         case RENDERPATH_GL11:
1936                 R_Mesh_TexBind(0, first );
1937                 break;
1938         case RENDERPATH_SOFT:
1939                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1940                 R_Mesh_TexBind(GL20TU_FIRST , first );
1941                 R_Mesh_TexBind(GL20TU_SECOND, second);
1942                 break;
1943         }
1944 }
1945
1946 void R_SetupShader_DepthOrShadow(void)
1947 {
1948         switch (vid.renderpath)
1949         {
1950         case RENDERPATH_D3D9:
1951 #ifdef SUPPORTD3D
1952                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1953 #endif
1954                 break;
1955         case RENDERPATH_D3D10:
1956                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1957                 break;
1958         case RENDERPATH_D3D11:
1959                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1960                 break;
1961         case RENDERPATH_GL20:
1962         case RENDERPATH_GLES2:
1963                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1964                 break;
1965         case RENDERPATH_GL13:
1966                 R_Mesh_TexBind(0, 0);
1967                 R_Mesh_TexBind(1, 0);
1968                 break;
1969         case RENDERPATH_GL11:
1970                 R_Mesh_TexBind(0, 0);
1971                 break;
1972         case RENDERPATH_SOFT:
1973                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1974                 break;
1975         }
1976 }
1977
1978 void R_SetupShader_ShowDepth(void)
1979 {
1980         switch (vid.renderpath)
1981         {
1982         case RENDERPATH_D3D9:
1983 #ifdef SUPPORTHLSL
1984                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1985 #endif
1986                 break;
1987         case RENDERPATH_D3D10:
1988                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1989                 break;
1990         case RENDERPATH_D3D11:
1991                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1992                 break;
1993         case RENDERPATH_GL20:
1994         case RENDERPATH_GLES2:
1995                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1996                 break;
1997         case RENDERPATH_GL13:
1998                 break;
1999         case RENDERPATH_GL11:
2000                 break;
2001         case RENDERPATH_SOFT:
2002                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2003                 break;
2004         }
2005 }
2006
2007 extern qboolean r_shadow_usingdeferredprepass;
2008 extern cvar_t r_shadow_deferred_8bitrange;
2009 extern rtexture_t *r_shadow_attenuationgradienttexture;
2010 extern rtexture_t *r_shadow_attenuation2dtexture;
2011 extern rtexture_t *r_shadow_attenuation3dtexture;
2012 extern qboolean r_shadow_usingshadowmap2d;
2013 extern qboolean r_shadow_usingshadowmaportho;
2014 extern float r_shadow_shadowmap_texturescale[2];
2015 extern float r_shadow_shadowmap_parameters[4];
2016 extern qboolean r_shadow_shadowmapvsdct;
2017 extern qboolean r_shadow_shadowmapsampler;
2018 extern int r_shadow_shadowmappcf;
2019 extern rtexture_t *r_shadow_shadowmap2dtexture;
2020 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2021 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2022 extern matrix4x4_t r_shadow_shadowmapmatrix;
2023 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2024 extern int r_shadow_prepass_width;
2025 extern int r_shadow_prepass_height;
2026 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2027 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2028 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2029 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2030 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2031
2032 #define BLENDFUNC_ALLOWS_COLORMOD      1
2033 #define BLENDFUNC_ALLOWS_FOG           2
2034 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2035 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2036 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2037 static int R_BlendFuncFlags(int src, int dst)
2038 {
2039         int r = 0;
2040
2041         // a blendfunc allows colormod if:
2042         // a) it can never keep the destination pixel invariant, or
2043         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2044         // this is to prevent unintended side effects from colormod
2045
2046         // a blendfunc allows fog if:
2047         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2048         // this is to prevent unintended side effects from fog
2049
2050         // these checks are the output of fogeval.pl
2051
2052         r |= BLENDFUNC_ALLOWS_COLORMOD;
2053         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2054         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2055         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2056         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2057         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2058         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2059         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2061         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2062         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2063         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2064         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2065         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2066         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2067         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2068         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2069         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2070         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2071         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2072         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2073         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2074
2075         return r;
2076 }
2077
2078 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)
2079 {
2080         // select a permutation of the lighting shader appropriate to this
2081         // combination of texture, entity, light source, and fogging, only use the
2082         // minimum features necessary to avoid wasting rendering time in the
2083         // fragment shader on features that are not being used
2084         unsigned int permutation = 0;
2085         unsigned int mode = 0;
2086         int blendfuncflags;
2087         static float dummy_colormod[3] = {1, 1, 1};
2088         float *colormod = rsurface.colormod;
2089         float m16f[16];
2090         matrix4x4_t tempmatrix;
2091         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2092         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2093                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2094         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2095                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2096         if (rsurfacepass == RSURFPASS_BACKGROUND)
2097         {
2098                 // distorted background
2099                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2100                 {
2101                         mode = SHADERMODE_WATER;
2102                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2103                         {
2104                                 // this is the right thing to do for wateralpha
2105                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2106                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2107                         }
2108                         else
2109                         {
2110                                 // this is the right thing to do for entity alpha
2111                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2112                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2113                         }
2114                 }
2115                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2116                 {
2117                         mode = SHADERMODE_REFRACTION;
2118                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2119                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2120                 }
2121                 else
2122                 {
2123                         mode = SHADERMODE_GENERIC;
2124                         permutation |= SHADERPERMUTATION_DIFFUSE;
2125                         GL_BlendFunc(GL_ONE, GL_ZERO);
2126                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2127                 }
2128         }
2129         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2130         {
2131                 if (r_glsl_offsetmapping.integer)
2132                 {
2133                         switch(rsurface.texture->offsetmapping)
2134                         {
2135                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2136                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2137                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2138                         case OFFSETMAPPING_OFF: break;
2139                         }
2140                 }
2141                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2142                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2143                 // normalmap (deferred prepass), may use alpha test on diffuse
2144                 mode = SHADERMODE_DEFERREDGEOMETRY;
2145                 GL_BlendFunc(GL_ONE, GL_ZERO);
2146                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2147         }
2148         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2149         {
2150                 if (r_glsl_offsetmapping.integer)
2151                 {
2152                         switch(rsurface.texture->offsetmapping)
2153                         {
2154                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2155                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2156                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2157                         case OFFSETMAPPING_OFF: break;
2158                         }
2159                 }
2160                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2161                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2162                 // light source
2163                 mode = SHADERMODE_LIGHTSOURCE;
2164                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2165                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2166                 if (diffusescale > 0)
2167                         permutation |= SHADERPERMUTATION_DIFFUSE;
2168                 if (specularscale > 0)
2169                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2170                 if (r_refdef.fogenabled)
2171                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2172                 if (rsurface.texture->colormapping)
2173                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2174                 if (r_shadow_usingshadowmap2d)
2175                 {
2176                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2177                         if(r_shadow_shadowmapvsdct)
2178                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2179
2180                         if (r_shadow_shadowmapsampler)
2181                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2182                         if (r_shadow_shadowmappcf > 1)
2183                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2184                         else if (r_shadow_shadowmappcf)
2185                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2186                 }
2187                 if (rsurface.texture->reflectmasktexture)
2188                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2189                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2190                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2191         }
2192         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2193         {
2194                 if (r_glsl_offsetmapping.integer)
2195                 {
2196                         switch(rsurface.texture->offsetmapping)
2197                         {
2198                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2199                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2200                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201                         case OFFSETMAPPING_OFF: break;
2202                         }
2203                 }
2204                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2205                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2206                 // unshaded geometry (fullbright or ambient model lighting)
2207                 mode = SHADERMODE_FLATCOLOR;
2208                 ambientscale = diffusescale = specularscale = 0;
2209                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2210                         permutation |= SHADERPERMUTATION_GLOW;
2211                 if (r_refdef.fogenabled)
2212                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2213                 if (rsurface.texture->colormapping)
2214                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2215                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2216                 {
2217                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2218                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2219
2220                         if (r_shadow_shadowmapsampler)
2221                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2222                         if (r_shadow_shadowmappcf > 1)
2223                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2224                         else if (r_shadow_shadowmappcf)
2225                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2226                 }
2227                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2228                         permutation |= SHADERPERMUTATION_REFLECTION;
2229                 if (rsurface.texture->reflectmasktexture)
2230                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2231                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2232                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2233         }
2234         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2235         {
2236                 if (r_glsl_offsetmapping.integer)
2237                 {
2238                         switch(rsurface.texture->offsetmapping)
2239                         {
2240                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2241                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2242                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2243                         case OFFSETMAPPING_OFF: break;
2244                         }
2245                 }
2246                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2247                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2248                 // directional model lighting
2249                 mode = SHADERMODE_LIGHTDIRECTION;
2250                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2251                         permutation |= SHADERPERMUTATION_GLOW;
2252                 permutation |= SHADERPERMUTATION_DIFFUSE;
2253                 if (specularscale > 0)
2254                         permutation |= SHADERPERMUTATION_SPECULAR;
2255                 if (r_refdef.fogenabled)
2256                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2257                 if (rsurface.texture->colormapping)
2258                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2259                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2260                 {
2261                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2262                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2263
2264                         if (r_shadow_shadowmapsampler)
2265                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2266                         if (r_shadow_shadowmappcf > 1)
2267                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2268                         else if (r_shadow_shadowmappcf)
2269                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2270                 }
2271                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2272                         permutation |= SHADERPERMUTATION_REFLECTION;
2273                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2274                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2275                 if (rsurface.texture->reflectmasktexture)
2276                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2277                 if (r_shadow_bouncegridtexture)
2278                 {
2279                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2280                         if (r_shadow_bouncegriddirectional)
2281                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2282                 }
2283                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2284                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2285         }
2286         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2287         {
2288                 if (r_glsl_offsetmapping.integer)
2289                 {
2290                         switch(rsurface.texture->offsetmapping)
2291                         {
2292                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2293                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2294                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2295                         case OFFSETMAPPING_OFF: break;
2296                         }
2297                 }
2298                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2299                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2300                 // ambient model lighting
2301                 mode = SHADERMODE_LIGHTDIRECTION;
2302                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2303                         permutation |= SHADERPERMUTATION_GLOW;
2304                 if (r_refdef.fogenabled)
2305                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2306                 if (rsurface.texture->colormapping)
2307                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2308                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2309                 {
2310                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2311                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2312
2313                         if (r_shadow_shadowmapsampler)
2314                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2315                         if (r_shadow_shadowmappcf > 1)
2316                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2317                         else if (r_shadow_shadowmappcf)
2318                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2319                 }
2320                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2321                         permutation |= SHADERPERMUTATION_REFLECTION;
2322                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2323                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2324                 if (rsurface.texture->reflectmasktexture)
2325                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2326                 if (r_shadow_bouncegridtexture)
2327                 {
2328                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2329                         if (r_shadow_bouncegriddirectional)
2330                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2331                 }
2332                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2333                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2334         }
2335         else
2336         {
2337                 if (r_glsl_offsetmapping.integer)
2338                 {
2339                         switch(rsurface.texture->offsetmapping)
2340                         {
2341                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2342                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2343                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2344                         case OFFSETMAPPING_OFF: break;
2345                         }
2346                 }
2347                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2348                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2349                 // lightmapped wall
2350                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2351                         permutation |= SHADERPERMUTATION_GLOW;
2352                 if (r_refdef.fogenabled)
2353                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2354                 if (rsurface.texture->colormapping)
2355                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2356                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2357                 {
2358                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2359                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2360
2361                         if (r_shadow_shadowmapsampler)
2362                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2363                         if (r_shadow_shadowmappcf > 1)
2364                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2365                         else if (r_shadow_shadowmappcf)
2366                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2367                 }
2368                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2369                         permutation |= SHADERPERMUTATION_REFLECTION;
2370                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2371                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2372                 if (rsurface.texture->reflectmasktexture)
2373                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2374                 if (FAKELIGHT_ENABLED)
2375                 {
2376                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2377                         mode = SHADERMODE_FAKELIGHT;
2378                         permutation |= SHADERPERMUTATION_DIFFUSE;
2379                         if (specularscale > 0)
2380                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2381                 }
2382                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2383                 {
2384                         // deluxemapping (light direction texture)
2385                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2386                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2387                         else
2388                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2389                         permutation |= SHADERPERMUTATION_DIFFUSE;
2390                         if (specularscale > 0)
2391                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2392                 }
2393                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2394                 {
2395                         // fake deluxemapping (uniform light direction in tangentspace)
2396                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2397                         permutation |= SHADERPERMUTATION_DIFFUSE;
2398                         if (specularscale > 0)
2399                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2400                 }
2401                 else if (rsurface.uselightmaptexture)
2402                 {
2403                         // ordinary lightmapping (q1bsp, q3bsp)
2404                         mode = SHADERMODE_LIGHTMAP;
2405                 }
2406                 else
2407                 {
2408                         // ordinary vertex coloring (q3bsp)
2409                         mode = SHADERMODE_VERTEXCOLOR;
2410                 }
2411                 if (r_shadow_bouncegridtexture)
2412                 {
2413                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2414                         if (r_shadow_bouncegriddirectional)
2415                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2416                 }
2417                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2418                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2419         }
2420         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2421                 colormod = dummy_colormod;
2422         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2423                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2424         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2425                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2426         switch(vid.renderpath)
2427         {
2428         case RENDERPATH_D3D9:
2429 #ifdef SUPPORTD3D
2430                 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);
2431                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2432                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2433                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2434                 if (mode == SHADERMODE_LIGHTSOURCE)
2435                 {
2436                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2437                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2438                 }
2439                 else
2440                 {
2441                         if (mode == SHADERMODE_LIGHTDIRECTION)
2442                         {
2443                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2444                         }
2445                 }
2446                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2447                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2448                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2449                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2450                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2451
2452                 if (mode == SHADERMODE_LIGHTSOURCE)
2453                 {
2454                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2455                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2456                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2457                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2458                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2459
2460                         // additive passes are only darkened by fog, not tinted
2461                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2462                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2463                 }
2464                 else
2465                 {
2466                         if (mode == SHADERMODE_FLATCOLOR)
2467                         {
2468                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2469                         }
2470                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2471                         {
2472                                 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]);
2473                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2474                                 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);
2475                                 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);
2476                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2477                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2478                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2479                         }
2480                         else
2481                         {
2482                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2483                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2484                                 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);
2485                                 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);
2486                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2487                         }
2488                         // additive passes are only darkened by fog, not tinted
2489                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2490                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2491                         else
2492                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2493                         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);
2494                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2495                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2496                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2497                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2498                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2499                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2500                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2501                         if (mode == SHADERMODE_WATER)
2502                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2503                 }
2504                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2505                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2506                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2507                 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));
2508                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2509                 if (rsurface.texture->pantstexture)
2510                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2511                 else
2512                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2513                 if (rsurface.texture->shirttexture)
2514                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2515                 else
2516                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2517                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2518                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2519                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2520                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2521                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2522                                 r_glsl_offsetmapping_scale.value,
2523                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2524                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2525                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2526                         );
2527                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2528                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2529
2530                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2531                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2532                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2533                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2534                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2535                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2536                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2537                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2538                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2539                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2540                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2541                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2542                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2543                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2544                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2545                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2546                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2547                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2548                 {
2549                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2550                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2551                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2552                 }
2553                 else
2554                 {
2555                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2556                 }
2557 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2558 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2559                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2560                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2561                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2562                 {
2563                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2564                         if (rsurface.rtlight)
2565                         {
2566                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2567                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2568                         }
2569                 }
2570 #endif
2571                 break;
2572         case RENDERPATH_D3D10:
2573                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2574                 break;
2575         case RENDERPATH_D3D11:
2576                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2577                 break;
2578         case RENDERPATH_GL20:
2579         case RENDERPATH_GLES2:
2580                 if (!vid.useinterleavedarrays)
2581                 {
2582                         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);
2583                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2584                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2585                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2586                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2587                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2588                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2589                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2590                 }
2591                 else
2592                 {
2593                         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);
2594                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2595                 }
2596                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2597                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2598                 if (mode == SHADERMODE_LIGHTSOURCE)
2599                 {
2600                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2601                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2602                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2603                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2604                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2605                         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);
2606         
2607                         // additive passes are only darkened by fog, not tinted
2608                         if (r_glsl_permutation->loc_FogColor >= 0)
2609                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2610                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2611                 }
2612                 else
2613                 {
2614                         if (mode == SHADERMODE_FLATCOLOR)
2615                         {
2616                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2617                         }
2618                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2619                         {
2620                                 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]);
2621                                 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]);
2622                                 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);
2623                                 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);
2624                                 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);
2625                                 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]);
2626                                 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]);
2627                         }
2628                         else
2629                         {
2630                                 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]);
2631                                 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]);
2632                                 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);
2633                                 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);
2634                                 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);
2635                         }
2636                         // additive passes are only darkened by fog, not tinted
2637                         if (r_glsl_permutation->loc_FogColor >= 0)
2638                         {
2639                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2640                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2641                                 else
2642                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2643                         }
2644                         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);
2645                         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]);
2646                         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]);
2647                         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]);
2648                         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]);
2649                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2650                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2651                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2652                         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]);
2653                 }
2654                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2655                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2656                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2657                 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]);
2658                 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]);
2659
2660                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2661                 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));
2662                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2663                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2664                 {
2665                         if (rsurface.texture->pantstexture)
2666                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2667                         else
2668                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2669                 }
2670                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2671                 {
2672                         if (rsurface.texture->shirttexture)
2673                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2674                         else
2675                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2676                 }
2677                 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]);
2678                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2679                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2680                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2681                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2682                                 r_glsl_offsetmapping_scale.value,
2683                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2684                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2685                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2686                         );
2687                 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]);
2688                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2689                 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);}
2690                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2691
2692                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2693                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2694                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2695                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2696                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2697                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2698                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2699                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2700                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2701                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2702                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2703                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2704                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2705                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2706                 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);
2707                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2708                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2709                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2710                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2711                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2712                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2713                 {
2714                         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);
2715                         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);
2716                         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);
2717                 }
2718                 else
2719                 {
2720                         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);
2721                 }
2722                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2723                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2724                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2725                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2726                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2727                 {
2728                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2729                         if (rsurface.rtlight)
2730                         {
2731                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2732                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2733                         }
2734                 }
2735                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2736                 CHECKGLERROR
2737                 break;
2738         case RENDERPATH_GL13:
2739         case RENDERPATH_GL11:
2740                 break;
2741         case RENDERPATH_SOFT:
2742                 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);
2743                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2744                 R_SetupShader_SetPermutationSoft(mode, permutation);
2745                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2746                 if (mode == SHADERMODE_LIGHTSOURCE)
2747                 {
2748                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2749                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2750                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2751                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2752                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2753                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2754         
2755                         // additive passes are only darkened by fog, not tinted
2756                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2757                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2758                 }
2759                 else
2760                 {
2761                         if (mode == SHADERMODE_FLATCOLOR)
2762                         {
2763                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2764                         }
2765                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2766                         {
2767                                 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]);
2768                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2769                                 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);
2770                                 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);
2771                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2772                                 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]);
2773                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2774                         }
2775                         else
2776                         {
2777                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2778                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2779                                 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);
2780                                 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);
2781                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2782                         }
2783                         // additive passes are only darkened by fog, not tinted
2784                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2785                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2786                         else
2787                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2788                         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);
2789                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2790                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2791                         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]);
2792                         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]);
2793                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2794                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2795                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2796                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2797                 }
2798                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2799                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2800                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2801                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2802                 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]);
2803
2804                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2805                 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));
2806                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2807                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2808                 {
2809                         if (rsurface.texture->pantstexture)
2810                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2811                         else
2812                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2813                 }
2814                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2815                 {
2816                         if (rsurface.texture->shirttexture)
2817                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2818                         else
2819                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2820                 }
2821                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2822                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2823                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2824                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2825                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2826                                 r_glsl_offsetmapping_scale.value,
2827                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2828                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2829                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2830                         );
2831                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2832                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2833
2834                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2835                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2836                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2837                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2838                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2839                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2840                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2841                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2842                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2843                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2844                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2845                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2846                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2847                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2848                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2849                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2850                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2851                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2852                 {
2853                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2854                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2855                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2856                 }
2857                 else
2858                 {
2859                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2860                 }
2861 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2862 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2863                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2864                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2865                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2866                 {
2867                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2868                         if (rsurface.rtlight)
2869                         {
2870                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2871                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2872                         }
2873                 }
2874                 break;
2875         }
2876 }
2877
2878 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2879 {
2880         // select a permutation of the lighting shader appropriate to this
2881         // combination of texture, entity, light source, and fogging, only use the
2882         // minimum features necessary to avoid wasting rendering time in the
2883         // fragment shader on features that are not being used
2884         unsigned int permutation = 0;
2885         unsigned int mode = 0;
2886         const float *lightcolorbase = rtlight->currentcolor;
2887         float ambientscale = rtlight->ambientscale;
2888         float diffusescale = rtlight->diffusescale;
2889         float specularscale = rtlight->specularscale;
2890         // this is the location of the light in view space
2891         vec3_t viewlightorigin;
2892         // this transforms from view space (camera) to light space (cubemap)
2893         matrix4x4_t viewtolight;
2894         matrix4x4_t lighttoview;
2895         float viewtolight16f[16];
2896         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2897         // light source
2898         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2899         if (rtlight->currentcubemap != r_texture_whitecube)
2900                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2901         if (diffusescale > 0)
2902                 permutation |= SHADERPERMUTATION_DIFFUSE;
2903         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2904                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2905         if (r_shadow_usingshadowmap2d)
2906         {
2907                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2908                 if (r_shadow_shadowmapvsdct)
2909                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2910
2911                 if (r_shadow_shadowmapsampler)
2912                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2913                 if (r_shadow_shadowmappcf > 1)
2914                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2915                 else if (r_shadow_shadowmappcf)
2916                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2917         }
2918         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2919         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2920         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2921         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2922         switch(vid.renderpath)
2923         {
2924         case RENDERPATH_D3D9:
2925 #ifdef SUPPORTD3D
2926                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2927                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2928                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2929                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2930                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2931                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2932                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2933                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2934                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2935                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2936                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2937
2938                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2939                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2940                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2941                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2942                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2943                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2944 #endif
2945                 break;
2946         case RENDERPATH_D3D10:
2947                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2948                 break;
2949         case RENDERPATH_D3D11:
2950                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2951                 break;
2952         case RENDERPATH_GL20:
2953         case RENDERPATH_GLES2:
2954                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2955                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2956                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2957                 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);
2958                 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);
2959                 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);
2960                 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]);
2961                 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]);
2962                 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));
2963                 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]);
2964                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2965
2966                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2967                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2968                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2969                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2970                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2971                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2972                 break;
2973         case RENDERPATH_GL13:
2974         case RENDERPATH_GL11:
2975                 break;
2976         case RENDERPATH_SOFT:
2977                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2978                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2979                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2980                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2981                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2982                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2983                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2984                 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]);
2985                 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));
2986                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2987                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2988
2989                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2990                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2991                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2992                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2993                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2994                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2995                 break;
2996         }
2997 }
2998
2999 #define SKINFRAME_HASH 1024
3000
3001 typedef struct
3002 {
3003         int loadsequence; // incremented each level change
3004         memexpandablearray_t array;
3005         skinframe_t *hash[SKINFRAME_HASH];
3006 }
3007 r_skinframe_t;
3008 r_skinframe_t r_skinframe;
3009
3010 void R_SkinFrame_PrepareForPurge(void)
3011 {
3012         r_skinframe.loadsequence++;
3013         // wrap it without hitting zero
3014         if (r_skinframe.loadsequence >= 200)
3015                 r_skinframe.loadsequence = 1;
3016 }
3017
3018 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3019 {
3020         if (!skinframe)
3021                 return;
3022         // mark the skinframe as used for the purging code
3023         skinframe->loadsequence = r_skinframe.loadsequence;
3024 }
3025
3026 void R_SkinFrame_Purge(void)
3027 {
3028         int i;
3029         skinframe_t *s;
3030         for (i = 0;i < SKINFRAME_HASH;i++)
3031         {
3032                 for (s = r_skinframe.hash[i];s;s = s->next)
3033                 {
3034                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3035                         {
3036                                 if (s->merged == s->base)
3037                                         s->merged = NULL;
3038                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3039                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3040                                 R_PurgeTexture(s->merged);s->merged = NULL;
3041                                 R_PurgeTexture(s->base  );s->base   = NULL;
3042                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3043                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3044                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3045                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3046                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3047                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3048                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3049                                 s->loadsequence = 0;
3050                         }
3051                 }
3052         }
3053 }
3054
3055 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3056         skinframe_t *item;
3057         char basename[MAX_QPATH];
3058
3059         Image_StripImageExtension(name, basename, sizeof(basename));
3060
3061         if( last == NULL ) {
3062                 int hashindex;
3063                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3064                 item = r_skinframe.hash[hashindex];
3065         } else {
3066                 item = last->next;
3067         }
3068
3069         // linearly search through the hash bucket
3070         for( ; item ; item = item->next ) {
3071                 if( !strcmp( item->basename, basename ) ) {
3072                         return item;
3073                 }
3074         }
3075         return NULL;
3076 }
3077
3078 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3079 {
3080         skinframe_t *item;
3081         int hashindex;
3082         char basename[MAX_QPATH];
3083
3084         Image_StripImageExtension(name, basename, sizeof(basename));
3085
3086         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3087         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3088                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3089                         break;
3090
3091         if (!item) {
3092                 rtexture_t *dyntexture;
3093                 // check whether its a dynamic texture
3094                 dyntexture = CL_GetDynTexture( basename );
3095                 if (!add && !dyntexture)
3096                         return NULL;
3097                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3098                 memset(item, 0, sizeof(*item));
3099                 strlcpy(item->basename, basename, sizeof(item->basename));
3100                 item->base = dyntexture; // either NULL or dyntexture handle
3101                 item->textureflags = textureflags;
3102                 item->comparewidth = comparewidth;
3103                 item->compareheight = compareheight;
3104                 item->comparecrc = comparecrc;
3105                 item->next = r_skinframe.hash[hashindex];
3106                 r_skinframe.hash[hashindex] = item;
3107         }
3108         else if( item->base == NULL )
3109         {
3110                 rtexture_t *dyntexture;
3111                 // check whether its a dynamic texture
3112                 // 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]
3113                 dyntexture = CL_GetDynTexture( basename );
3114                 item->base = dyntexture; // either NULL or dyntexture handle
3115         }
3116
3117         R_SkinFrame_MarkUsed(item);
3118         return item;
3119 }
3120
3121 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3122         { \
3123                 unsigned long long avgcolor[5], wsum; \
3124                 int pix, comp, w; \
3125                 avgcolor[0] = 0; \
3126                 avgcolor[1] = 0; \
3127                 avgcolor[2] = 0; \
3128                 avgcolor[3] = 0; \
3129                 avgcolor[4] = 0; \
3130                 wsum = 0; \
3131                 for(pix = 0; pix < cnt; ++pix) \
3132                 { \
3133                         w = 0; \
3134                         for(comp = 0; comp < 3; ++comp) \
3135                                 w += getpixel; \
3136                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3137                         { \
3138                                 ++wsum; \
3139                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3140                                 w = getpixel; \
3141                                 for(comp = 0; comp < 3; ++comp) \
3142                                         avgcolor[comp] += getpixel * w; \
3143                                 avgcolor[3] += w; \
3144                         } \
3145                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3146                         avgcolor[4] += getpixel; \
3147                 } \
3148                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3149                         avgcolor[3] = 1; \
3150                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3151                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3152                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3153                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3154         }
3155
3156 extern cvar_t gl_picmip;
3157 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3158 {
3159         int j;
3160         unsigned char *pixels;
3161         unsigned char *bumppixels;
3162         unsigned char *basepixels = NULL;
3163         int basepixels_width = 0;
3164         int basepixels_height = 0;
3165         skinframe_t *skinframe;
3166         rtexture_t *ddsbase = NULL;
3167         qboolean ddshasalpha = false;
3168         float ddsavgcolor[4];
3169         char basename[MAX_QPATH];
3170         int miplevel = R_PicmipForFlags(textureflags);
3171         int savemiplevel = miplevel;
3172         int mymiplevel;
3173
3174         if (cls.state == ca_dedicated)
3175                 return NULL;
3176
3177         // return an existing skinframe if already loaded
3178         // if loading of the first image fails, don't make a new skinframe as it
3179         // would cause all future lookups of this to be missing
3180         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3181         if (skinframe && skinframe->base)
3182                 return skinframe;
3183
3184         Image_StripImageExtension(name, basename, sizeof(basename));
3185
3186         // check for DDS texture file first
3187         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3188         {
3189                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3190                 if (basepixels == NULL)
3191                         return NULL;
3192         }
3193
3194         // FIXME handle miplevel
3195
3196         if (developer_loading.integer)
3197                 Con_Printf("loading skin \"%s\"\n", name);
3198
3199         // we've got some pixels to store, so really allocate this new texture now
3200         if (!skinframe)
3201                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3202         skinframe->stain = NULL;
3203         skinframe->merged = NULL;
3204         skinframe->base = NULL;
3205         skinframe->pants = NULL;
3206         skinframe->shirt = NULL;
3207         skinframe->nmap = NULL;
3208         skinframe->gloss = NULL;
3209         skinframe->glow = NULL;
3210         skinframe->fog = NULL;
3211         skinframe->reflect = NULL;
3212         skinframe->hasalpha = false;
3213
3214         if (ddsbase)
3215         {
3216                 skinframe->base = ddsbase;
3217                 skinframe->hasalpha = ddshasalpha;
3218                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3219                 if (r_loadfog && skinframe->hasalpha)
3220                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3221                 //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]);
3222         }
3223         else
3224         {
3225                 basepixels_width = image_width;
3226                 basepixels_height = image_height;
3227                 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);
3228                 if (textureflags & TEXF_ALPHA)
3229                 {
3230                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3231                         {
3232                                 if (basepixels[j] < 255)
3233                                 {
3234                                         skinframe->hasalpha = true;
3235                                         break;
3236                                 }
3237                         }
3238                         if (r_loadfog && skinframe->hasalpha)
3239                         {
3240                                 // has transparent pixels
3241                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3242                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3243                                 {
3244                                         pixels[j+0] = 255;
3245                                         pixels[j+1] = 255;
3246                                         pixels[j+2] = 255;
3247                                         pixels[j+3] = basepixels[j+3];
3248                                 }
3249                                 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);
3250                                 Mem_Free(pixels);
3251                         }
3252                 }
3253                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3254                 //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]);
3255                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3256                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3257                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3258                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3259         }
3260
3261         if (r_loaddds)
3262         {
3263                 mymiplevel = savemiplevel;
3264                 if (r_loadnormalmap)
3265                         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);
3266                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3267                 if (r_loadgloss)
3268                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3269                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3270                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3271                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3272         }
3273
3274         // _norm is the name used by tenebrae and has been adopted as standard
3275         if (r_loadnormalmap && skinframe->nmap == NULL)
3276         {
3277                 mymiplevel = savemiplevel;
3278                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3279                 {
3280                         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);
3281                         Mem_Free(pixels);
3282                         pixels = NULL;
3283                 }
3284                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3285                 {
3286                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3287                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3288                         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);
3289                         Mem_Free(pixels);
3290                         Mem_Free(bumppixels);
3291                 }
3292                 else if (r_shadow_bumpscale_basetexture.value > 0)
3293                 {
3294                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3295                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3296                         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);
3297                         Mem_Free(pixels);
3298                 }
3299                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3300                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3301         }
3302
3303         // _luma is supported only for tenebrae compatibility
3304         // _glow is the preferred name
3305         mymiplevel = savemiplevel;
3306         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))))
3307         {
3308                 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);
3309                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3310                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3311                 Mem_Free(pixels);pixels = NULL;
3312         }
3313
3314         mymiplevel = savemiplevel;
3315         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3316         {
3317                 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);
3318                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3319                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3320                 Mem_Free(pixels);
3321                 pixels = NULL;
3322         }
3323
3324         mymiplevel = savemiplevel;
3325         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3326         {
3327                 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);
3328                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3329                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3330                 Mem_Free(pixels);
3331                 pixels = NULL;
3332         }
3333
3334         mymiplevel = savemiplevel;
3335         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3336         {
3337                 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);
3338                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3339                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3340                 Mem_Free(pixels);
3341                 pixels = NULL;
3342         }
3343
3344         mymiplevel = savemiplevel;
3345         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3346         {
3347                 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);
3348                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3349                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3350                 Mem_Free(pixels);
3351                 pixels = NULL;
3352         }
3353
3354         if (basepixels)
3355                 Mem_Free(basepixels);
3356
3357         return skinframe;
3358 }
3359
3360 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3361 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3362 {
3363         int i;
3364         unsigned char *temp1, *temp2;
3365         skinframe_t *skinframe;
3366
3367         if (cls.state == ca_dedicated)
3368                 return NULL;
3369
3370         // if already loaded just return it, otherwise make a new skinframe
3371         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3372         if (skinframe && skinframe->base)
3373                 return skinframe;
3374
3375         skinframe->stain = NULL;
3376         skinframe->merged = NULL;
3377         skinframe->base = NULL;
3378         skinframe->pants = NULL;
3379         skinframe->shirt = NULL;
3380         skinframe->nmap = NULL;
3381         skinframe->gloss = NULL;
3382         skinframe->glow = NULL;
3383         skinframe->fog = NULL;
3384         skinframe->reflect = NULL;
3385         skinframe->hasalpha = false;
3386
3387         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3388         if (!skindata)
3389                 return NULL;
3390
3391         if (developer_loading.integer)
3392                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3393
3394         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3395         {
3396                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3397                 temp2 = temp1 + width * height * 4;
3398                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3399                 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);
3400                 Mem_Free(temp1);
3401         }
3402         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3403         if (textureflags & TEXF_ALPHA)
3404         {
3405                 for (i = 3;i < width * height * 4;i += 4)
3406                 {
3407                         if (skindata[i] < 255)
3408                         {
3409                                 skinframe->hasalpha = true;
3410                                 break;
3411                         }
3412                 }
3413                 if (r_loadfog && skinframe->hasalpha)
3414                 {
3415                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3416                         memcpy(fogpixels, skindata, width * height * 4);
3417                         for (i = 0;i < width * height * 4;i += 4)
3418                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3419                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3420                         Mem_Free(fogpixels);
3421                 }
3422         }
3423
3424         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3425         //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]);
3426
3427         return skinframe;
3428 }
3429
3430 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3431 {
3432         int i;
3433         int featuresmask;
3434         skinframe_t *skinframe;
3435
3436         if (cls.state == ca_dedicated)
3437                 return NULL;
3438
3439         // if already loaded just return it, otherwise make a new skinframe
3440         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3441         if (skinframe && skinframe->base)
3442                 return skinframe;
3443
3444         skinframe->stain = NULL;
3445         skinframe->merged = NULL;
3446         skinframe->base = NULL;
3447         skinframe->pants = NULL;
3448         skinframe->shirt = NULL;
3449         skinframe->nmap = NULL;
3450         skinframe->gloss = NULL;
3451         skinframe->glow = NULL;
3452         skinframe->fog = NULL;
3453         skinframe->reflect = NULL;
3454         skinframe->hasalpha = false;
3455
3456         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3457         if (!skindata)
3458                 return NULL;
3459
3460         if (developer_loading.integer)
3461                 Con_Printf("loading quake skin \"%s\"\n", name);
3462
3463         // 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)
3464         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3465         memcpy(skinframe->qpixels, skindata, width*height);
3466         skinframe->qwidth = width;
3467         skinframe->qheight = height;
3468
3469         featuresmask = 0;
3470         for (i = 0;i < width * height;i++)
3471                 featuresmask |= palette_featureflags[skindata[i]];
3472
3473         skinframe->hasalpha = false;
3474         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3475         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3476         skinframe->qgeneratemerged = true;
3477         skinframe->qgeneratebase = skinframe->qhascolormapping;
3478         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3479
3480         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3481         //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]);
3482
3483         return skinframe;
3484 }
3485
3486 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3487 {
3488         int width;
3489         int height;
3490         unsigned char *skindata;
3491
3492         if (!skinframe->qpixels)
3493                 return;
3494
3495         if (!skinframe->qhascolormapping)
3496                 colormapped = false;
3497
3498         if (colormapped)
3499         {
3500                 if (!skinframe->qgeneratebase)
3501                         return;
3502         }
3503         else
3504         {
3505                 if (!skinframe->qgeneratemerged)
3506                         return;
3507         }
3508
3509         width = skinframe->qwidth;
3510         height = skinframe->qheight;
3511         skindata = skinframe->qpixels;
3512
3513         if (skinframe->qgeneratenmap)
3514         {
3515                 unsigned char *temp1, *temp2;
3516                 skinframe->qgeneratenmap = false;
3517                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3518                 temp2 = temp1 + width * height * 4;
3519                 // use either a custom palette or the quake palette
3520                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3521                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3522                 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);
3523                 Mem_Free(temp1);
3524         }
3525
3526         if (skinframe->qgenerateglow)
3527         {
3528                 skinframe->qgenerateglow = false;
3529                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3530         }
3531
3532         if (colormapped)
3533         {
3534                 skinframe->qgeneratebase = false;
3535                 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);
3536                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3537                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3538         }
3539         else
3540         {
3541                 skinframe->qgeneratemerged = false;
3542                 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);
3543         }
3544
3545         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3546         {
3547                 Mem_Free(skinframe->qpixels);
3548                 skinframe->qpixels = NULL;
3549         }
3550 }
3551
3552 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)
3553 {
3554         int i;
3555         skinframe_t *skinframe;
3556
3557         if (cls.state == ca_dedicated)
3558                 return NULL;
3559
3560         // if already loaded just return it, otherwise make a new skinframe
3561         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3562         if (skinframe && skinframe->base)
3563                 return skinframe;
3564
3565         skinframe->stain = NULL;
3566         skinframe->merged = NULL;
3567         skinframe->base = NULL;
3568         skinframe->pants = NULL;
3569         skinframe->shirt = NULL;
3570         skinframe->nmap = NULL;
3571         skinframe->gloss = NULL;
3572         skinframe->glow = NULL;
3573         skinframe->fog = NULL;
3574         skinframe->reflect = NULL;
3575         skinframe->hasalpha = false;
3576
3577         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3578         if (!skindata)
3579                 return NULL;
3580
3581         if (developer_loading.integer)
3582                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3583
3584         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3585         if (textureflags & TEXF_ALPHA)
3586         {
3587                 for (i = 0;i < width * height;i++)
3588                 {
3589                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3590                         {
3591                                 skinframe->hasalpha = true;
3592                                 break;
3593                         }
3594                 }
3595                 if (r_loadfog && skinframe->hasalpha)
3596                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3597         }
3598
3599         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3600         //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]);
3601
3602         return skinframe;
3603 }
3604
3605 skinframe_t *R_SkinFrame_LoadMissing(void)
3606 {
3607         skinframe_t *skinframe;
3608
3609         if (cls.state == ca_dedicated)
3610                 return NULL;
3611
3612         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3613         skinframe->stain = NULL;
3614         skinframe->merged = NULL;
3615         skinframe->base = NULL;
3616         skinframe->pants = NULL;
3617         skinframe->shirt = NULL;
3618         skinframe->nmap = NULL;
3619         skinframe->gloss = NULL;
3620         skinframe->glow = NULL;
3621         skinframe->fog = NULL;
3622         skinframe->reflect = NULL;
3623         skinframe->hasalpha = false;
3624
3625         skinframe->avgcolor[0] = rand() / RAND_MAX;
3626         skinframe->avgcolor[1] = rand() / RAND_MAX;
3627         skinframe->avgcolor[2] = rand() / RAND_MAX;
3628         skinframe->avgcolor[3] = 1;
3629
3630         return skinframe;
3631 }
3632
3633 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3634 typedef struct suffixinfo_s
3635 {
3636         const char *suffix;
3637         qboolean flipx, flipy, flipdiagonal;
3638 }
3639 suffixinfo_t;
3640 static suffixinfo_t suffix[3][6] =
3641 {
3642         {
3643                 {"px",   false, false, false},
3644                 {"nx",   false, false, false},
3645                 {"py",   false, false, false},
3646                 {"ny",   false, false, false},
3647                 {"pz",   false, false, false},
3648                 {"nz",   false, false, false}
3649         },
3650         {
3651                 {"posx", false, false, false},
3652                 {"negx", false, false, false},
3653                 {"posy", false, false, false},
3654                 {"negy", false, false, false},
3655                 {"posz", false, false, false},
3656                 {"negz", false, false, false}
3657         },
3658         {
3659                 {"rt",    true, false,  true},
3660                 {"lf",   false,  true,  true},
3661                 {"ft",    true,  true, false},
3662                 {"bk",   false, false, false},
3663                 {"up",    true, false,  true},
3664                 {"dn",    true, false,  true}
3665         }
3666 };
3667
3668 static int componentorder[4] = {0, 1, 2, 3};
3669
3670 rtexture_t *R_LoadCubemap(const char *basename)
3671 {
3672         int i, j, cubemapsize;
3673         unsigned char *cubemappixels, *image_buffer;
3674         rtexture_t *cubemaptexture;
3675         char name[256];
3676         // must start 0 so the first loadimagepixels has no requested width/height
3677         cubemapsize = 0;
3678         cubemappixels = NULL;
3679         cubemaptexture = NULL;
3680         // keep trying different suffix groups (posx, px, rt) until one loads
3681         for (j = 0;j < 3 && !cubemappixels;j++)
3682         {
3683                 // load the 6 images in the suffix group
3684                 for (i = 0;i < 6;i++)
3685                 {
3686                         // generate an image name based on the base and and suffix
3687                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3688                         // load it
3689                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3690                         {
3691                                 // an image loaded, make sure width and height are equal
3692                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3693                                 {
3694                                         // if this is the first image to load successfully, allocate the cubemap memory
3695                                         if (!cubemappixels && image_width >= 1)
3696                                         {
3697                                                 cubemapsize = image_width;
3698                                                 // note this clears to black, so unavailable sides are black
3699                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3700                                         }
3701                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3702                                         if (cubemappixels)
3703                                                 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);
3704                                 }
3705                                 else
3706                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3707                                 // free the image
3708                                 Mem_Free(image_buffer);
3709                         }
3710                 }
3711         }
3712         // if a cubemap loaded, upload it
3713         if (cubemappixels)
3714         {
3715                 if (developer_loading.integer)
3716                         Con_Printf("loading cubemap \"%s\"\n", basename);
3717
3718                 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);
3719                 Mem_Free(cubemappixels);
3720         }
3721         else
3722         {
3723                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3724                 if (developer_loading.integer)
3725                 {
3726                         Con_Printf("(tried tried images ");
3727                         for (j = 0;j < 3;j++)
3728                                 for (i = 0;i < 6;i++)
3729                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3730                         Con_Print(" and was unable to find any of them).\n");
3731                 }
3732         }
3733         return cubemaptexture;
3734 }
3735
3736 rtexture_t *R_GetCubemap(const char *basename)
3737 {
3738         int i;
3739         for (i = 0;i < r_texture_numcubemaps;i++)
3740                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3741                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3742         if (i >= MAX_CUBEMAPS)
3743                 return r_texture_whitecube;
3744         r_texture_numcubemaps++;
3745         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3746         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3747         return r_texture_cubemaps[i].texture;
3748 }
3749
3750 void R_FreeCubemaps(void)
3751 {
3752         int i;
3753         for (i = 0;i < r_texture_numcubemaps;i++)
3754         {
3755                 if (developer_loading.integer)
3756                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3757                 if (r_texture_cubemaps[i].texture)
3758                         R_FreeTexture(r_texture_cubemaps[i].texture);
3759         }
3760         r_texture_numcubemaps = 0;
3761 }
3762
3763 void R_Main_FreeViewCache(void)
3764 {
3765         if (r_refdef.viewcache.entityvisible)
3766                 Mem_Free(r_refdef.viewcache.entityvisible);
3767         if (r_refdef.viewcache.world_pvsbits)
3768                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3769         if (r_refdef.viewcache.world_leafvisible)
3770                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3771         if (r_refdef.viewcache.world_surfacevisible)
3772                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3773         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3774 }
3775
3776 void R_Main_ResizeViewCache(void)
3777 {
3778         int numentities = r_refdef.scene.numentities;
3779         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3780         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3781         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3782         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3783         if (r_refdef.viewcache.maxentities < numentities)
3784         {
3785                 r_refdef.viewcache.maxentities = numentities;
3786                 if (r_refdef.viewcache.entityvisible)
3787                         Mem_Free(r_refdef.viewcache.entityvisible);
3788                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3789         }
3790         if (r_refdef.viewcache.world_numclusters != numclusters)
3791         {
3792                 r_refdef.viewcache.world_numclusters = numclusters;
3793                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3794                 if (r_refdef.viewcache.world_pvsbits)
3795                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3796                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3797         }
3798         if (r_refdef.viewcache.world_numleafs != numleafs)
3799         {
3800                 r_refdef.viewcache.world_numleafs = numleafs;
3801                 if (r_refdef.viewcache.world_leafvisible)
3802                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3803                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3804         }
3805         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3806         {
3807                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3808                 if (r_refdef.viewcache.world_surfacevisible)
3809                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3810                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3811         }
3812 }
3813
3814 extern rtexture_t *loadingscreentexture;
3815 void gl_main_start(void)
3816 {
3817         loadingscreentexture = NULL;
3818         r_texture_blanknormalmap = NULL;
3819         r_texture_white = NULL;
3820         r_texture_grey128 = NULL;
3821         r_texture_black = NULL;
3822         r_texture_whitecube = NULL;
3823         r_texture_normalizationcube = NULL;
3824         r_texture_fogattenuation = NULL;
3825         r_texture_fogheighttexture = NULL;
3826         r_texture_gammaramps = NULL;
3827         r_texture_numcubemaps = 0;
3828
3829         r_loaddds = r_texture_dds_load.integer != 0;
3830         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3831
3832         switch(vid.renderpath)
3833         {
3834         case RENDERPATH_GL20:
3835         case RENDERPATH_D3D9:
3836         case RENDERPATH_D3D10:
3837         case RENDERPATH_D3D11:
3838         case RENDERPATH_SOFT:
3839         case RENDERPATH_GLES2:
3840                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3841                 Cvar_SetValueQuick(&gl_combine, 1);
3842                 Cvar_SetValueQuick(&r_glsl, 1);
3843                 r_loadnormalmap = true;
3844                 r_loadgloss = true;
3845                 r_loadfog = false;
3846                 break;
3847         case RENDERPATH_GL13:
3848                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3849                 Cvar_SetValueQuick(&gl_combine, 1);
3850                 Cvar_SetValueQuick(&r_glsl, 0);
3851                 r_loadnormalmap = false;
3852                 r_loadgloss = false;
3853                 r_loadfog = true;
3854                 break;
3855         case RENDERPATH_GL11:
3856                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3857                 Cvar_SetValueQuick(&gl_combine, 0);
3858                 Cvar_SetValueQuick(&r_glsl, 0);
3859                 r_loadnormalmap = false;
3860                 r_loadgloss = false;
3861                 r_loadfog = true;
3862                 break;
3863         }
3864
3865         R_AnimCache_Free();
3866         R_FrameData_Reset();
3867
3868         r_numqueries = 0;
3869         r_maxqueries = 0;
3870         memset(r_queries, 0, sizeof(r_queries));
3871
3872         r_qwskincache = NULL;
3873         r_qwskincache_size = 0;
3874
3875         // due to caching of texture_t references, the collision cache must be reset
3876         Collision_Cache_Reset(true);
3877
3878         // set up r_skinframe loading system for textures
3879         memset(&r_skinframe, 0, sizeof(r_skinframe));
3880         r_skinframe.loadsequence = 1;
3881         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3882
3883         r_main_texturepool = R_AllocTexturePool();
3884         R_BuildBlankTextures();
3885         R_BuildNoTexture();
3886         if (vid.support.arb_texture_cube_map)
3887         {
3888                 R_BuildWhiteCube();
3889                 R_BuildNormalizationCube();
3890         }
3891         r_texture_fogattenuation = NULL;
3892         r_texture_fogheighttexture = NULL;
3893         r_texture_gammaramps = NULL;
3894         //r_texture_fogintensity = NULL;
3895         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3896         memset(&r_waterstate, 0, sizeof(r_waterstate));
3897         r_glsl_permutation = NULL;
3898         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3899         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3900         glslshaderstring = NULL;
3901 #ifdef SUPPORTD3D
3902         r_hlsl_permutation = NULL;
3903         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3904         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3905 #endif
3906         hlslshaderstring = NULL;
3907         memset(&r_svbsp, 0, sizeof (r_svbsp));
3908
3909         r_refdef.fogmasktable_density = 0;
3910 }
3911
3912 void gl_main_shutdown(void)
3913 {
3914         R_AnimCache_Free();
3915         R_FrameData_Reset();
3916
3917         R_Main_FreeViewCache();
3918
3919         switch(vid.renderpath)
3920         {
3921         case RENDERPATH_GL11:
3922         case RENDERPATH_GL13:
3923         case RENDERPATH_GL20:
3924         case RENDERPATH_GLES2:
3925                 if (r_maxqueries)
3926                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3927                 break;
3928         case RENDERPATH_D3D9:
3929                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3930                 break;
3931         case RENDERPATH_D3D10:
3932                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3933                 break;
3934         case RENDERPATH_D3D11:
3935                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3936                 break;
3937         case RENDERPATH_SOFT:
3938                 break;
3939         }
3940
3941         r_numqueries = 0;
3942         r_maxqueries = 0;
3943         memset(r_queries, 0, sizeof(r_queries));
3944
3945         r_qwskincache = NULL;
3946         r_qwskincache_size = 0;
3947
3948         // clear out the r_skinframe state
3949         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3950         memset(&r_skinframe, 0, sizeof(r_skinframe));
3951
3952         if (r_svbsp.nodes)
3953                 Mem_Free(r_svbsp.nodes);
3954         memset(&r_svbsp, 0, sizeof (r_svbsp));
3955         R_FreeTexturePool(&r_main_texturepool);
3956         loadingscreentexture = NULL;
3957         r_texture_blanknormalmap = NULL;
3958         r_texture_white = NULL;
3959         r_texture_grey128 = NULL;
3960         r_texture_black = NULL;
3961         r_texture_whitecube = NULL;
3962         r_texture_normalizationcube = NULL;
3963         r_texture_fogattenuation = NULL;
3964         r_texture_fogheighttexture = NULL;
3965         r_texture_gammaramps = NULL;
3966         r_texture_numcubemaps = 0;
3967         //r_texture_fogintensity = NULL;
3968         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3969         memset(&r_waterstate, 0, sizeof(r_waterstate));
3970         R_GLSL_Restart_f();
3971
3972         r_glsl_permutation = NULL;
3973         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3974         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3975         glslshaderstring = NULL;
3976 #ifdef SUPPORTD3D
3977         r_hlsl_permutation = NULL;
3978         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3979         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3980 #endif
3981         hlslshaderstring = NULL;
3982 }
3983
3984 extern void CL_ParseEntityLump(char *entitystring);
3985 void gl_main_newmap(void)
3986 {
3987         // FIXME: move this code to client
3988         char *entities, entname[MAX_QPATH];
3989         if (r_qwskincache)
3990                 Mem_Free(r_qwskincache);
3991         r_qwskincache = NULL;
3992         r_qwskincache_size = 0;
3993         if (cl.worldmodel)
3994         {
3995                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3996                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3997                 {
3998                         CL_ParseEntityLump(entities);
3999                         Mem_Free(entities);
4000                         return;
4001                 }
4002                 if (cl.worldmodel->brush.entities)
4003                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4004         }
4005         R_Main_FreeViewCache();
4006
4007         R_FrameData_Reset();
4008 }
4009
4010 void GL_Main_Init(void)
4011 {
4012         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4013
4014         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4015         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4016         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4017         if (gamemode == GAME_NEHAHRA)
4018         {
4019                 Cvar_RegisterVariable (&gl_fogenable);
4020                 Cvar_RegisterVariable (&gl_fogdensity);
4021                 Cvar_RegisterVariable (&gl_fogred);
4022                 Cvar_RegisterVariable (&gl_foggreen);
4023                 Cvar_RegisterVariable (&gl_fogblue);
4024                 Cvar_RegisterVariable (&gl_fogstart);
4025                 Cvar_RegisterVariable (&gl_fogend);
4026                 Cvar_RegisterVariable (&gl_skyclip);
4027         }
4028         Cvar_RegisterVariable(&r_motionblur);
4029         Cvar_RegisterVariable(&r_motionblur_maxblur);
4030         Cvar_RegisterVariable(&r_motionblur_bmin);
4031         Cvar_RegisterVariable(&r_motionblur_vmin);
4032         Cvar_RegisterVariable(&r_motionblur_vmax);
4033         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4034         Cvar_RegisterVariable(&r_motionblur_randomize);
4035         Cvar_RegisterVariable(&r_damageblur);
4036         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4037         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4038         Cvar_RegisterVariable(&r_equalize_entities_by);
4039         Cvar_RegisterVariable(&r_equalize_entities_to);
4040         Cvar_RegisterVariable(&r_depthfirst);
4041         Cvar_RegisterVariable(&r_useinfinitefarclip);
4042         Cvar_RegisterVariable(&r_farclip_base);
4043         Cvar_RegisterVariable(&r_farclip_world);
4044         Cvar_RegisterVariable(&r_nearclip);
4045         Cvar_RegisterVariable(&r_showbboxes);
4046         Cvar_RegisterVariable(&r_showsurfaces);
4047         Cvar_RegisterVariable(&r_showtris);
4048         Cvar_RegisterVariable(&r_shownormals);
4049         Cvar_RegisterVariable(&r_showlighting);
4050         Cvar_RegisterVariable(&r_showshadowvolumes);
4051         Cvar_RegisterVariable(&r_showcollisionbrushes);
4052         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4053         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4054         Cvar_RegisterVariable(&r_showdisabledepthtest);
4055         Cvar_RegisterVariable(&r_drawportals);
4056         Cvar_RegisterVariable(&r_drawentities);
4057         Cvar_RegisterVariable(&r_draw2d);
4058         Cvar_RegisterVariable(&r_drawworld);
4059         Cvar_RegisterVariable(&r_cullentities_trace);
4060         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4061         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4062         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4063         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4064         Cvar_RegisterVariable(&r_drawviewmodel);
4065         Cvar_RegisterVariable(&r_drawexteriormodel);
4066         Cvar_RegisterVariable(&r_speeds);
4067         Cvar_RegisterVariable(&r_fullbrights);
4068         Cvar_RegisterVariable(&r_wateralpha);
4069         Cvar_RegisterVariable(&r_dynamic);
4070         Cvar_RegisterVariable(&r_fakelight);
4071         Cvar_RegisterVariable(&r_fakelight_intensity);
4072         Cvar_RegisterVariable(&r_fullbright);
4073         Cvar_RegisterVariable(&r_shadows);
4074         Cvar_RegisterVariable(&r_shadows_darken);
4075         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4076         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4077         Cvar_RegisterVariable(&r_shadows_throwdistance);
4078         Cvar_RegisterVariable(&r_shadows_throwdirection);
4079         Cvar_RegisterVariable(&r_shadows_focus);
4080         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4081         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4082         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4083         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4084         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4085         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4086         Cvar_RegisterVariable(&r_fog_exp2);
4087         Cvar_RegisterVariable(&r_fog_clear);
4088         Cvar_RegisterVariable(&r_drawfog);
4089         Cvar_RegisterVariable(&r_transparentdepthmasking);
4090         Cvar_RegisterVariable(&r_texture_dds_load);
4091         Cvar_RegisterVariable(&r_texture_dds_save);
4092         Cvar_RegisterVariable(&r_texture_sRGB_2d);
4093         Cvar_RegisterVariable(&r_texture_sRGB_skin_diffuse);
4094         Cvar_RegisterVariable(&r_texture_sRGB_skin_gloss);
4095         Cvar_RegisterVariable(&r_texture_sRGB_skin_glow);
4096         Cvar_RegisterVariable(&r_texture_sRGB_skin_reflect);
4097         Cvar_RegisterVariable(&r_texture_sRGB_cubemap);
4098         Cvar_RegisterVariable(&r_texture_sRGB_skybox);
4099         Cvar_RegisterVariable(&r_textureunits);
4100         Cvar_RegisterVariable(&gl_combine);
4101         Cvar_RegisterVariable(&r_viewfbo);
4102         Cvar_RegisterVariable(&r_viewscale);
4103         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4104         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4105         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4106         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4107         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4108         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4109         Cvar_RegisterVariable(&r_glsl);
4110         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4111         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4112         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4113         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4114         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4115         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4116         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4117         Cvar_RegisterVariable(&r_glsl_postprocess);
4118         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4119         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4120         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4121         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4122         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4123         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4124         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4125         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4126
4127         Cvar_RegisterVariable(&r_water);
4128         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4129         Cvar_RegisterVariable(&r_water_clippingplanebias);
4130         Cvar_RegisterVariable(&r_water_refractdistort);
4131         Cvar_RegisterVariable(&r_water_reflectdistort);
4132         Cvar_RegisterVariable(&r_water_scissormode);
4133         Cvar_RegisterVariable(&r_lerpsprites);
4134         Cvar_RegisterVariable(&r_lerpmodels);
4135         Cvar_RegisterVariable(&r_lerplightstyles);
4136         Cvar_RegisterVariable(&r_waterscroll);
4137         Cvar_RegisterVariable(&r_bloom);
4138         Cvar_RegisterVariable(&r_bloom_colorscale);
4139         Cvar_RegisterVariable(&r_bloom_brighten);
4140         Cvar_RegisterVariable(&r_bloom_blur);
4141         Cvar_RegisterVariable(&r_bloom_resolution);
4142         Cvar_RegisterVariable(&r_bloom_colorexponent);
4143         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4144         Cvar_RegisterVariable(&r_hdr);
4145         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4146         Cvar_RegisterVariable(&r_hdr_glowintensity);
4147         Cvar_RegisterVariable(&r_hdr_range);
4148         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4149         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4150         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4151         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4152         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4153         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4154         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4155         Cvar_RegisterVariable(&developer_texturelogging);
4156         Cvar_RegisterVariable(&gl_lightmaps);
4157         Cvar_RegisterVariable(&r_test);
4158         Cvar_RegisterVariable(&r_glsl_saturation);
4159         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4160         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4161         Cvar_RegisterVariable(&r_framedatasize);
4162         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4163                 Cvar_SetValue("r_fullbrights", 0);
4164         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4165
4166         Cvar_RegisterVariable(&r_track_sprites);
4167         Cvar_RegisterVariable(&r_track_sprites_flags);
4168         Cvar_RegisterVariable(&r_track_sprites_scalew);
4169         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4170         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4171         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4172         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4173         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4174 }
4175
4176 extern void R_Textures_Init(void);
4177 extern void GL_Draw_Init(void);
4178 extern void GL_Main_Init(void);
4179 extern void R_Shadow_Init(void);
4180 extern void R_Sky_Init(void);
4181 extern void GL_Surf_Init(void);
4182 extern void R_Particles_Init(void);
4183 extern void R_Explosion_Init(void);
4184 extern void gl_backend_init(void);
4185 extern void Sbar_Init(void);
4186 extern void R_LightningBeams_Init(void);
4187 extern void Mod_RenderInit(void);
4188 extern void Font_Init(void);
4189
4190 void Render_Init(void)
4191 {
4192         gl_backend_init();
4193         R_Textures_Init();
4194         GL_Main_Init();
4195         Font_Init();
4196         GL_Draw_Init();
4197         R_Shadow_Init();
4198         R_Sky_Init();
4199         GL_Surf_Init();
4200         Sbar_Init();
4201         R_Particles_Init();
4202         R_Explosion_Init();
4203         R_LightningBeams_Init();
4204         Mod_RenderInit();
4205 }
4206
4207 /*
4208 ===============
4209 GL_Init
4210 ===============
4211 */
4212 extern char *ENGINE_EXTENSIONS;
4213 void GL_Init (void)
4214 {
4215         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4216         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4217         gl_version = (const char *)qglGetString(GL_VERSION);
4218         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4219
4220         if (!gl_extensions)
4221                 gl_extensions = "";
4222         if (!gl_platformextensions)
4223                 gl_platformextensions = "";
4224
4225         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4226         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4227         Con_Printf("GL_VERSION: %s\n", gl_version);
4228         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4229         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4230
4231         VID_CheckExtensions();
4232
4233         // LordHavoc: report supported extensions
4234         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4235
4236         // clear to black (loading plaque will be seen over this)
4237         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4238 }
4239
4240 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4241 {
4242         int i;
4243         mplane_t *p;
4244         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4245         {
4246                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4247                 if (i == 4)
4248                         continue;
4249                 p = r_refdef.view.frustum + i;
4250                 switch(p->signbits)
4251                 {
4252                 default:
4253                 case 0:
4254                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4255                                 return true;
4256                         break;
4257                 case 1:
4258                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4259                                 return true;
4260                         break;
4261                 case 2:
4262                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4263                                 return true;
4264                         break;
4265                 case 3:
4266                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4267                                 return true;
4268                         break;
4269                 case 4:
4270                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4271                                 return true;
4272                         break;
4273                 case 5:
4274                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4275                                 return true;
4276                         break;
4277                 case 6:
4278                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4279                                 return true;
4280                         break;
4281                 case 7:
4282                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4283                                 return true;
4284                         break;
4285                 }
4286         }
4287         return false;
4288 }
4289
4290 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4291 {
4292         int i;
4293         const mplane_t *p;
4294         for (i = 0;i < numplanes;i++)
4295         {
4296                 p = planes + i;
4297                 switch(p->signbits)
4298                 {
4299                 default:
4300                 case 0:
4301                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4302                                 return true;
4303                         break;
4304                 case 1:
4305                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4306                                 return true;
4307                         break;
4308                 case 2:
4309                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4310                                 return true;
4311                         break;
4312                 case 3:
4313                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4314                                 return true;
4315                         break;
4316                 case 4:
4317                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4318                                 return true;
4319                         break;
4320                 case 5:
4321                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4322                                 return true;
4323                         break;
4324                 case 6:
4325                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4326                                 return true;
4327                         break;
4328                 case 7:
4329                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4330                                 return true;
4331                         break;
4332                 }
4333         }
4334         return false;
4335 }
4336
4337 //==================================================================================
4338
4339 // LordHavoc: this stores temporary data used within the same frame
4340
4341 typedef struct r_framedata_mem_s
4342 {
4343         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4344         size_t size; // how much usable space
4345         size_t current; // how much space in use
4346         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4347         size_t wantedsize; // how much space was allocated
4348         unsigned char *data; // start of real data (16byte aligned)
4349 }
4350 r_framedata_mem_t;
4351
4352 static r_framedata_mem_t *r_framedata_mem;
4353
4354 void R_FrameData_Reset(void)
4355 {
4356         while (r_framedata_mem)
4357         {
4358                 r_framedata_mem_t *next = r_framedata_mem->purge;
4359                 Mem_Free(r_framedata_mem);
4360                 r_framedata_mem = next;
4361         }
4362 }
4363
4364 void R_FrameData_Resize(void)
4365 {
4366         size_t wantedsize;
4367         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4368         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4369         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4370         {
4371                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4372                 newmem->wantedsize = wantedsize;
4373                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4374                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4375                 newmem->current = 0;
4376                 newmem->mark = 0;
4377                 newmem->purge = r_framedata_mem;
4378                 r_framedata_mem = newmem;
4379         }
4380 }
4381
4382 void R_FrameData_NewFrame(void)
4383 {
4384         R_FrameData_Resize();
4385         if (!r_framedata_mem)
4386                 return;
4387         // if we ran out of space on the last frame, free the old memory now
4388         while (r_framedata_mem->purge)
4389         {
4390                 // repeatedly remove the second item in the list, leaving only head
4391                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4392                 Mem_Free(r_framedata_mem->purge);
4393                 r_framedata_mem->purge = next;
4394         }
4395         // reset the current mem pointer
4396         r_framedata_mem->current = 0;
4397         r_framedata_mem->mark = 0;
4398 }
4399
4400 void *R_FrameData_Alloc(size_t size)
4401 {
4402         void *data;
4403
4404         // align to 16 byte boundary - the data pointer is already aligned, so we
4405         // only need to ensure the size of every allocation is also aligned
4406         size = (size + 15) & ~15;
4407
4408         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4409         {
4410                 // emergency - we ran out of space, allocate more memory
4411                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4412                 R_FrameData_Resize();
4413         }
4414
4415         data = r_framedata_mem->data + r_framedata_mem->current;
4416         r_framedata_mem->current += size;
4417
4418         // count the usage for stats
4419         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4420         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4421
4422         return (void *)data;
4423 }
4424
4425 void *R_FrameData_Store(size_t size, void *data)
4426 {
4427         void *d = R_FrameData_Alloc(size);
4428         if (d && data)
4429                 memcpy(d, data, size);
4430         return d;
4431 }
4432
4433 void R_FrameData_SetMark(void)
4434 {
4435         if (!r_framedata_mem)
4436                 return;
4437         r_framedata_mem->mark = r_framedata_mem->current;
4438 }
4439
4440 void R_FrameData_ReturnToMark(void)
4441 {
4442         if (!r_framedata_mem)
4443                 return;
4444         r_framedata_mem->current = r_framedata_mem->mark;
4445 }
4446
4447 //==================================================================================
4448
4449 // LordHavoc: animcache originally written by Echon, rewritten since then
4450
4451 /**
4452  * Animation cache prevents re-generating mesh data for an animated model
4453  * multiple times in one frame for lighting, shadowing, reflections, etc.
4454  */
4455
4456 void R_AnimCache_Free(void)
4457 {
4458 }
4459
4460 void R_AnimCache_ClearCache(void)
4461 {
4462         int i;
4463         entity_render_t *ent;
4464
4465         for (i = 0;i < r_refdef.scene.numentities;i++)
4466         {
4467                 ent = r_refdef.scene.entities[i];
4468                 ent->animcache_vertex3f = NULL;
4469                 ent->animcache_normal3f = NULL;
4470                 ent->animcache_svector3f = NULL;
4471                 ent->animcache_tvector3f = NULL;
4472                 ent->animcache_vertexmesh = NULL;
4473                 ent->animcache_vertex3fbuffer = NULL;
4474                 ent->animcache_vertexmeshbuffer = NULL;
4475         }
4476 }
4477
4478 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4479 {
4480         int i;
4481
4482         // check if we need the meshbuffers
4483         if (!vid.useinterleavedarrays)
4484                 return;
4485
4486         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4487                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4488         // TODO: upload vertex3f buffer?
4489         if (ent->animcache_vertexmesh)
4490         {
4491                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4492                 for (i = 0;i < numvertices;i++)
4493                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4494                 if (ent->animcache_svector3f)
4495                         for (i = 0;i < numvertices;i++)
4496                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4497                 if (ent->animcache_tvector3f)
4498                         for (i = 0;i < numvertices;i++)
4499                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4500                 if (ent->animcache_normal3f)
4501                         for (i = 0;i < numvertices;i++)
4502                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4503                 // TODO: upload vertexmeshbuffer?
4504         }
4505 }
4506
4507 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4508 {
4509         dp_model_t *model = ent->model;
4510         int numvertices;
4511         // see if it's already cached this frame
4512         if (ent->animcache_vertex3f)
4513         {
4514                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4515                 if (wantnormals || wanttangents)
4516                 {
4517                         if (ent->animcache_normal3f)
4518                                 wantnormals = false;
4519                         if (ent->animcache_svector3f)
4520                                 wanttangents = false;
4521                         if (wantnormals || wanttangents)
4522                         {
4523                                 numvertices = model->surfmesh.num_vertices;
4524                                 if (wantnormals)
4525                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4526                                 if (wanttangents)
4527                                 {
4528                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4529                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4530                                 }
4531                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4532                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4533                         }
4534                 }
4535         }
4536         else
4537         {
4538                 // see if this ent is worth caching
4539                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4540                         return false;
4541                 // get some memory for this entity and generate mesh data
4542                 numvertices = model->surfmesh.num_vertices;
4543                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4544                 if (wantnormals)
4545                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4546                 if (wanttangents)
4547                 {
4548                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4549                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4550                 }
4551                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4552                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4553         }
4554         return true;
4555 }
4556
4557 void R_AnimCache_CacheVisibleEntities(void)
4558 {
4559         int i;
4560         qboolean wantnormals = true;
4561         qboolean wanttangents = !r_showsurfaces.integer;
4562
4563         switch(vid.renderpath)
4564         {
4565         case RENDERPATH_GL20:
4566         case RENDERPATH_D3D9:
4567         case RENDERPATH_D3D10:
4568         case RENDERPATH_D3D11:
4569         case RENDERPATH_GLES2:
4570                 break;
4571         case RENDERPATH_GL13:
4572         case RENDERPATH_GL11:
4573                 wanttangents = false;
4574                 break;
4575         case RENDERPATH_SOFT:
4576                 break;
4577         }
4578
4579         if (r_shownormals.integer)
4580                 wanttangents = wantnormals = true;
4581
4582         // TODO: thread this
4583         // NOTE: R_PrepareRTLights() also caches entities
4584
4585         for (i = 0;i < r_refdef.scene.numentities;i++)
4586                 if (r_refdef.viewcache.entityvisible[i])
4587                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4588 }
4589
4590 //==================================================================================
4591
4592 static void R_View_UpdateEntityLighting (void)
4593 {
4594         int i;
4595         entity_render_t *ent;
4596         vec3_t tempdiffusenormal, avg;
4597         vec_t f, fa, fd, fdd;
4598         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4599
4600         for (i = 0;i < r_refdef.scene.numentities;i++)
4601         {
4602                 ent = r_refdef.scene.entities[i];
4603
4604                 // skip unseen models
4605                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4606                         continue;
4607
4608                 // skip bsp models
4609                 if (ent->model && ent->model->brush.num_leafs)
4610                 {
4611                         // TODO: use modellight for r_ambient settings on world?
4612                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4613                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4614                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4615                         continue;
4616                 }
4617
4618                 // fetch the lighting from the worldmodel data
4619                 VectorClear(ent->modellight_ambient);
4620                 VectorClear(ent->modellight_diffuse);
4621                 VectorClear(tempdiffusenormal);
4622                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4623                 {
4624                         vec3_t org;
4625                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4626
4627                         // complete lightning for lit sprites
4628                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4629                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4630                         {
4631                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4632                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4633                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4634                         }
4635                         else
4636                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4637
4638                         if(ent->flags & RENDER_EQUALIZE)
4639                         {
4640                                 // first fix up ambient lighting...
4641                                 if(r_equalize_entities_minambient.value > 0)
4642                                 {
4643                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4644                                         if(fd > 0)
4645                                         {
4646                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4647                                                 if(fa < r_equalize_entities_minambient.value * fd)
4648                                                 {
4649                                                         // solve:
4650                                                         //   fa'/fd' = minambient
4651                                                         //   fa'+0.25*fd' = fa+0.25*fd
4652                                                         //   ...
4653                                                         //   fa' = fd' * minambient
4654                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4655                                                         //   ...
4656                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4657                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4658                                                         //   ...
4659                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4660                                                         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
4661                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4662                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4663                                                 }
4664                                         }
4665                                 }
4666
4667                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4668                                 {
4669                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4670                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4671                                         f = fa + 0.25 * fd;
4672                                         if(f > 0)
4673                                         {
4674                                                 // adjust brightness and saturation to target
4675                                                 avg[0] = avg[1] = avg[2] = fa / f;
4676                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4677                                                 avg[0] = avg[1] = avg[2] = fd / f;
4678                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4679                                         }
4680                                 }
4681                         }
4682                 }
4683                 else // highly rare
4684                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4685
4686                 // move the light direction into modelspace coordinates for lighting code
4687                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4688                 if(VectorLength2(ent->modellight_lightdir) == 0)
4689                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4690                 VectorNormalize(ent->modellight_lightdir);
4691         }
4692 }
4693
4694 #define MAX_LINEOFSIGHTTRACES 64
4695
4696 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4697 {
4698         int i;
4699         vec3_t boxmins, boxmaxs;
4700         vec3_t start;
4701         vec3_t end;
4702         dp_model_t *model = r_refdef.scene.worldmodel;
4703
4704         if (!model || !model->brush.TraceLineOfSight)
4705                 return true;
4706
4707         // expand the box a little
4708         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4709         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4710         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4711         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4712         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4713         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4714
4715         // return true if eye is inside enlarged box
4716         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4717                 return true;
4718
4719         // try center
4720         VectorCopy(eye, start);
4721         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4722         if (model->brush.TraceLineOfSight(model, start, end))
4723                 return true;
4724
4725         // try various random positions
4726         for (i = 0;i < numsamples;i++)
4727         {
4728                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4729                 if (model->brush.TraceLineOfSight(model, start, end))
4730                         return true;
4731         }
4732
4733         return false;
4734 }
4735
4736
4737 static void R_View_UpdateEntityVisible (void)
4738 {
4739         int i;
4740         int renderimask;
4741         int samples;
4742         entity_render_t *ent;
4743
4744         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4745                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4746                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4747                 :                                                          RENDER_EXTERIORMODEL;
4748         if (!r_drawviewmodel.integer)
4749                 renderimask |= RENDER_VIEWMODEL;
4750         if (!r_drawexteriormodel.integer)
4751                 renderimask |= RENDER_EXTERIORMODEL;
4752         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4753         {
4754                 // worldmodel can check visibility
4755                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4756                 for (i = 0;i < r_refdef.scene.numentities;i++)
4757                 {
4758                         ent = r_refdef.scene.entities[i];
4759                         if (!(ent->flags & renderimask))
4760                         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)))
4761                         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))
4762                                 r_refdef.viewcache.entityvisible[i] = true;
4763                 }
4764                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4765                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4766                 {
4767                         for (i = 0;i < r_refdef.scene.numentities;i++)
4768                         {
4769                                 ent = r_refdef.scene.entities[i];
4770                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4771                                 {
4772                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4773                                         if (samples < 0)
4774                                                 continue; // temp entities do pvs only
4775                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4776                                                 ent->last_trace_visibility = realtime;
4777                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4778                                                 r_refdef.viewcache.entityvisible[i] = 0;
4779                                 }
4780                         }
4781                 }
4782         }
4783         else
4784         {
4785                 // no worldmodel or it can't check visibility
4786                 for (i = 0;i < r_refdef.scene.numentities;i++)
4787                 {
4788                         ent = r_refdef.scene.entities[i];
4789                         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));
4790                 }
4791         }
4792 }
4793
4794 /// only used if skyrendermasked, and normally returns false
4795 int R_DrawBrushModelsSky (void)
4796 {
4797         int i, sky;
4798         entity_render_t *ent;
4799
4800         sky = false;
4801         for (i = 0;i < r_refdef.scene.numentities;i++)
4802         {
4803                 if (!r_refdef.viewcache.entityvisible[i])
4804                         continue;
4805                 ent = r_refdef.scene.entities[i];
4806                 if (!ent->model || !ent->model->DrawSky)
4807                         continue;
4808                 ent->model->DrawSky(ent);
4809                 sky = true;
4810         }
4811         return sky;
4812 }
4813
4814 static void R_DrawNoModel(entity_render_t *ent);
4815 static void R_DrawModels(void)
4816 {
4817         int i;
4818         entity_render_t *ent;
4819
4820         for (i = 0;i < r_refdef.scene.numentities;i++)
4821         {
4822                 if (!r_refdef.viewcache.entityvisible[i])
4823                         continue;
4824                 ent = r_refdef.scene.entities[i];
4825                 r_refdef.stats.entities++;
4826                 if (ent->model && ent->model->Draw != NULL)
4827                         ent->model->Draw(ent);
4828                 else
4829                         R_DrawNoModel(ent);
4830         }
4831 }
4832
4833 static void R_DrawModelsDepth(void)
4834 {
4835         int i;
4836         entity_render_t *ent;
4837
4838         for (i = 0;i < r_refdef.scene.numentities;i++)
4839         {
4840                 if (!r_refdef.viewcache.entityvisible[i])
4841                         continue;
4842                 ent = r_refdef.scene.entities[i];
4843                 if (ent->model && ent->model->DrawDepth != NULL)
4844                         ent->model->DrawDepth(ent);
4845         }
4846 }
4847
4848 static void R_DrawModelsDebug(void)
4849 {
4850         int i;
4851         entity_render_t *ent;
4852
4853         for (i = 0;i < r_refdef.scene.numentities;i++)
4854         {
4855                 if (!r_refdef.viewcache.entityvisible[i])
4856                         continue;
4857                 ent = r_refdef.scene.entities[i];
4858                 if (ent->model && ent->model->DrawDebug != NULL)
4859                         ent->model->DrawDebug(ent);
4860         }
4861 }
4862
4863 static void R_DrawModelsAddWaterPlanes(void)
4864 {
4865         int i;
4866         entity_render_t *ent;
4867
4868         for (i = 0;i < r_refdef.scene.numentities;i++)
4869         {
4870                 if (!r_refdef.viewcache.entityvisible[i])
4871                         continue;
4872                 ent = r_refdef.scene.entities[i];
4873                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4874                         ent->model->DrawAddWaterPlanes(ent);
4875         }
4876 }
4877
4878 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4879 {
4880         if (r_hdr_irisadaptation.integer)
4881         {
4882                 vec3_t ambient;
4883                 vec3_t diffuse;
4884                 vec3_t diffusenormal;
4885                 vec_t brightness;
4886                 vec_t goal;
4887                 vec_t adjust;
4888                 vec_t current;
4889                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4890                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4891                 brightness = max(0.0000001f, brightness);
4892                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4893                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4894                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4895                 current = r_hdr_irisadaptation_value.value;
4896                 if (current < goal)
4897                         current = min(current + adjust, goal);
4898                 else if (current > goal)
4899                         current = max(current - adjust, goal);
4900                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4901                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4902         }
4903         else if (r_hdr_irisadaptation_value.value != 1.0f)
4904                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4905 }
4906
4907 static void R_View_SetFrustum(const int *scissor)
4908 {
4909         int i;
4910         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4911         vec3_t forward, left, up, origin, v;
4912
4913         if(scissor)
4914         {
4915                 // flipped x coordinates (because x points left here)
4916                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4917                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4918
4919                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4920                 switch(vid.renderpath)
4921                 {
4922                         case RENDERPATH_D3D9:
4923                         case RENDERPATH_D3D10:
4924                         case RENDERPATH_D3D11:
4925                                 // non-flipped y coordinates
4926                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4927                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4928                                 break;
4929                         case RENDERPATH_SOFT:
4930                         case RENDERPATH_GL11:
4931                         case RENDERPATH_GL13:
4932                         case RENDERPATH_GL20:
4933                         case RENDERPATH_GLES2:
4934                                 // non-flipped y coordinates
4935                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4936                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4937                                 break;
4938                 }
4939         }
4940
4941         // we can't trust r_refdef.view.forward and friends in reflected scenes
4942         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4943
4944 #if 0
4945         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4946         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4947         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4948         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4949         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4950         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4951         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4952         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4953         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4954         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4955         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4956         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4957 #endif
4958
4959 #if 0
4960         zNear = r_refdef.nearclip;
4961         nudge = 1.0 - 1.0 / (1<<23);
4962         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4963         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4964         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4965         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4966         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4967         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4968         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4969         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4970 #endif
4971
4972
4973
4974 #if 0
4975         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4976         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4977         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4978         r_refdef.view.frustum[0].dist = m[15] - m[12];
4979
4980         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4981         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4982         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4983         r_refdef.view.frustum[1].dist = m[15] + m[12];
4984
4985         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4986         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4987         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4988         r_refdef.view.frustum[2].dist = m[15] - m[13];
4989
4990         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4991         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4992         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4993         r_refdef.view.frustum[3].dist = m[15] + m[13];
4994
4995         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4996         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4997         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4998         r_refdef.view.frustum[4].dist = m[15] - m[14];
4999
5000         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5001         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5002         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5003         r_refdef.view.frustum[5].dist = m[15] + m[14];
5004 #endif
5005
5006         if (r_refdef.view.useperspective)
5007         {
5008                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5009                 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]);
5010                 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]);
5011                 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]);
5012                 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]);
5013
5014                 // then the normals from the corners relative to origin
5015                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5016                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5017                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5018                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5019
5020                 // in a NORMAL view, forward cross left == up
5021                 // in a REFLECTED view, forward cross left == down
5022                 // so our cross products above need to be adjusted for a left handed coordinate system
5023                 CrossProduct(forward, left, v);
5024                 if(DotProduct(v, up) < 0)
5025                 {
5026                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5027                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5028                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5029                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5030                 }
5031
5032                 // Leaving those out was a mistake, those were in the old code, and they
5033                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5034                 // I couldn't reproduce it after adding those normalizations. --blub
5035                 VectorNormalize(r_refdef.view.frustum[0].normal);
5036                 VectorNormalize(r_refdef.view.frustum[1].normal);
5037                 VectorNormalize(r_refdef.view.frustum[2].normal);
5038                 VectorNormalize(r_refdef.view.frustum[3].normal);
5039
5040                 // make the corners absolute
5041                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5042                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5043                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5044                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5045
5046                 // one more normal
5047                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5048
5049                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5050                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5051                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5052                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5053                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5054         }
5055         else
5056         {
5057                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5058                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5059                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5060                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5061                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5062                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5063                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5064                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5065                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5066                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5067         }
5068         r_refdef.view.numfrustumplanes = 5;
5069
5070         if (r_refdef.view.useclipplane)
5071         {
5072                 r_refdef.view.numfrustumplanes = 6;
5073                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5074         }
5075
5076         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5077                 PlaneClassify(r_refdef.view.frustum + i);
5078
5079         // LordHavoc: note to all quake engine coders, Quake had a special case
5080         // for 90 degrees which assumed a square view (wrong), so I removed it,
5081         // Quake2 has it disabled as well.
5082
5083         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5084         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5085         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5086         //PlaneClassify(&frustum[0]);
5087
5088         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5089         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5090         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5091         //PlaneClassify(&frustum[1]);
5092
5093         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5094         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5095         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5096         //PlaneClassify(&frustum[2]);
5097
5098         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5099         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5100         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5101         //PlaneClassify(&frustum[3]);
5102
5103         // nearclip plane
5104         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5105         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5106         //PlaneClassify(&frustum[4]);
5107 }
5108
5109 void R_View_UpdateWithScissor(const int *myscissor)
5110 {
5111         R_Main_ResizeViewCache();
5112         R_View_SetFrustum(myscissor);
5113         R_View_WorldVisibility(r_refdef.view.useclipplane);
5114         R_View_UpdateEntityVisible();
5115         R_View_UpdateEntityLighting();
5116 }
5117
5118 void R_View_Update(void)
5119 {
5120         R_Main_ResizeViewCache();
5121         R_View_SetFrustum(NULL);
5122         R_View_WorldVisibility(r_refdef.view.useclipplane);
5123         R_View_UpdateEntityVisible();
5124         R_View_UpdateEntityLighting();
5125 }
5126
5127 float viewscalefpsadjusted = 1.0f;
5128
5129 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5130 {
5131         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5132         scale = bound(0.03125f, scale, 1.0f);
5133         *outwidth = (int)ceil(width * scale);
5134         *outheight = (int)ceil(height * scale);
5135 }
5136
5137 void R_Mesh_SetMainRenderTargets(void)
5138 {
5139         if (r_bloomstate.fbo_framebuffer)
5140                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5141         else
5142                 R_Mesh_ResetRenderTargets();
5143 }
5144
5145 void R_SetupView(qboolean allowwaterclippingplane)
5146 {
5147         const float *customclipplane = NULL;
5148         float plane[4];
5149         int scaledwidth, scaledheight;
5150         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5151         {
5152                 // LordHavoc: couldn't figure out how to make this approach the
5153                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5154                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5155                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5156                         dist = r_refdef.view.clipplane.dist;
5157                 plane[0] = r_refdef.view.clipplane.normal[0];
5158                 plane[1] = r_refdef.view.clipplane.normal[1];
5159                 plane[2] = r_refdef.view.clipplane.normal[2];
5160                 plane[3] = -dist;
5161                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5162         }
5163
5164         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5165         if (!r_refdef.view.useperspective)
5166                 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);
5167         else if (vid.stencil && r_useinfinitefarclip.integer)
5168                 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);
5169         else
5170                 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);
5171         R_Mesh_SetMainRenderTargets();
5172         R_SetViewport(&r_refdef.view.viewport);
5173         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5174         {
5175                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5176                 float screenplane[4];
5177                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5178                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5179                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5180                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5181                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5182         }
5183 }
5184
5185 void R_EntityMatrix(const matrix4x4_t *matrix)
5186 {
5187         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5188         {
5189                 gl_modelmatrixchanged = false;
5190                 gl_modelmatrix = *matrix;
5191                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5192                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5193                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5194                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5195                 CHECKGLERROR
5196                 switch(vid.renderpath)
5197                 {
5198                 case RENDERPATH_D3D9:
5199 #ifdef SUPPORTD3D
5200                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5201                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5202 #endif
5203                         break;
5204                 case RENDERPATH_D3D10:
5205                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5206                         break;
5207                 case RENDERPATH_D3D11:
5208                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5209                         break;
5210                 case RENDERPATH_GL13:
5211                 case RENDERPATH_GL11:
5212                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5213                         break;
5214                 case RENDERPATH_SOFT:
5215                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5216                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5217                         break;
5218                 case RENDERPATH_GL20:
5219                 case RENDERPATH_GLES2:
5220                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5221                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5222                         break;
5223                 }
5224         }
5225 }
5226
5227 void R_ResetViewRendering2D(void)
5228 {
5229         r_viewport_t viewport;
5230         DrawQ_Finish();
5231
5232         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5233         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);
5234         R_Mesh_ResetRenderTargets();
5235         R_SetViewport(&viewport);
5236         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5237         GL_Color(1, 1, 1, 1);
5238         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5239         GL_BlendFunc(GL_ONE, GL_ZERO);
5240         GL_ScissorTest(false);
5241         GL_DepthMask(false);
5242         GL_DepthRange(0, 1);
5243         GL_DepthTest(false);
5244         GL_DepthFunc(GL_LEQUAL);
5245         R_EntityMatrix(&identitymatrix);
5246         R_Mesh_ResetTextureState();
5247         GL_PolygonOffset(0, 0);
5248         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5249         switch(vid.renderpath)
5250         {
5251         case RENDERPATH_GL11:
5252         case RENDERPATH_GL13:
5253         case RENDERPATH_GL20:
5254         case RENDERPATH_GLES2:
5255                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5256                 break;
5257         case RENDERPATH_D3D9:
5258         case RENDERPATH_D3D10:
5259         case RENDERPATH_D3D11:
5260         case RENDERPATH_SOFT:
5261                 break;
5262         }
5263         GL_CullFace(GL_NONE);
5264 }
5265
5266 void R_ResetViewRendering3D(void)
5267 {
5268         DrawQ_Finish();
5269
5270         R_SetupView(true);
5271         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5272         GL_Color(1, 1, 1, 1);
5273         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5274         GL_BlendFunc(GL_ONE, GL_ZERO);
5275         GL_ScissorTest(true);
5276         GL_DepthMask(true);
5277         GL_DepthRange(0, 1);
5278         GL_DepthTest(true);
5279         GL_DepthFunc(GL_LEQUAL);
5280         R_EntityMatrix(&identitymatrix);
5281         R_Mesh_ResetTextureState();
5282         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5283         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5284         switch(vid.renderpath)
5285         {
5286         case RENDERPATH_GL11:
5287         case RENDERPATH_GL13:
5288         case RENDERPATH_GL20:
5289         case RENDERPATH_GLES2:
5290                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5291                 break;
5292         case RENDERPATH_D3D9:
5293         case RENDERPATH_D3D10:
5294         case RENDERPATH_D3D11:
5295         case RENDERPATH_SOFT:
5296                 break;
5297         }
5298         GL_CullFace(r_refdef.view.cullface_back);
5299 }
5300
5301 /*
5302 ================
5303 R_RenderView_UpdateViewVectors
5304 ================
5305 */
5306 static void R_RenderView_UpdateViewVectors(void)
5307 {
5308         // break apart the view matrix into vectors for various purposes
5309         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5310         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5311         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5312         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5313         // make an inverted copy of the view matrix for tracking sprites
5314         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5315 }
5316
5317 void R_RenderScene(void);
5318 void R_RenderWaterPlanes(void);
5319
5320 static void R_Water_StartFrame(void)
5321 {
5322         int i;
5323         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5324         r_waterstate_waterplane_t *p;
5325
5326         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5327                 return;
5328
5329         switch(vid.renderpath)
5330         {
5331         case RENDERPATH_GL20:
5332         case RENDERPATH_D3D9:
5333         case RENDERPATH_D3D10:
5334         case RENDERPATH_D3D11:
5335         case RENDERPATH_SOFT:
5336         case RENDERPATH_GLES2:
5337                 break;
5338         case RENDERPATH_GL13:
5339         case RENDERPATH_GL11:
5340                 return;
5341         }
5342
5343         // set waterwidth and waterheight to the water resolution that will be
5344         // used (often less than the screen resolution for faster rendering)
5345         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5346         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5347
5348         // calculate desired texture sizes
5349         // can't use water if the card does not support the texture size
5350         if (!r_water.integer || r_showsurfaces.integer)
5351                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5352         else if (vid.support.arb_texture_non_power_of_two)
5353         {
5354                 texturewidth = waterwidth;
5355                 textureheight = waterheight;
5356                 camerawidth = waterwidth;
5357                 cameraheight = waterheight;
5358         }
5359         else
5360         {
5361                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5362                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5363                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5364                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5365         }
5366
5367         // allocate textures as needed
5368         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5369         {
5370                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5371                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5372                 {
5373                         if (p->texture_refraction)
5374                                 R_FreeTexture(p->texture_refraction);
5375                         p->texture_refraction = NULL;
5376                         if (p->texture_reflection)
5377                                 R_FreeTexture(p->texture_reflection);
5378                         p->texture_reflection = NULL;
5379                         if (p->texture_camera)
5380                                 R_FreeTexture(p->texture_camera);
5381                         p->texture_camera = NULL;
5382                 }
5383                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5384                 r_waterstate.texturewidth = texturewidth;
5385                 r_waterstate.textureheight = textureheight;
5386                 r_waterstate.camerawidth = camerawidth;
5387                 r_waterstate.cameraheight = cameraheight;
5388         }
5389
5390         if (r_waterstate.texturewidth)
5391         {
5392                 r_waterstate.enabled = true;
5393
5394                 // when doing a reduced render (HDR) we want to use a smaller area
5395                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5396                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5397
5398                 // set up variables that will be used in shader setup
5399                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5400                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5401                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5402                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5403         }
5404
5405         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5406         r_waterstate.numwaterplanes = 0;
5407 }
5408
5409 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5410 {
5411         int triangleindex, planeindex;
5412         const int *e;
5413         vec3_t vert[3];
5414         vec3_t normal;
5415         vec3_t center;
5416         mplane_t plane;
5417         r_waterstate_waterplane_t *p;
5418         texture_t *t = R_GetCurrentTexture(surface->texture);
5419
5420         // just use the first triangle with a valid normal for any decisions
5421         VectorClear(normal);
5422         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5423         {
5424                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5425                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5426                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5427                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5428                 if (VectorLength2(normal) >= 0.001)
5429                         break;
5430         }
5431
5432         VectorCopy(normal, plane.normal);
5433         VectorNormalize(plane.normal);
5434         plane.dist = DotProduct(vert[0], plane.normal);
5435         PlaneClassify(&plane);
5436         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5437         {
5438                 // skip backfaces (except if nocullface is set)
5439                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5440                         return;
5441                 VectorNegate(plane.normal, plane.normal);
5442                 plane.dist *= -1;
5443                 PlaneClassify(&plane);
5444         }
5445
5446
5447         // find a matching plane if there is one
5448         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5449                 if(p->camera_entity == t->camera_entity)
5450                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5451                                 break;
5452         if (planeindex >= r_waterstate.maxwaterplanes)
5453                 return; // nothing we can do, out of planes
5454
5455         // if this triangle does not fit any known plane rendered this frame, add one
5456         if (planeindex >= r_waterstate.numwaterplanes)
5457         {
5458                 // store the new plane
5459                 r_waterstate.numwaterplanes++;
5460                 p->plane = plane;
5461                 // clear materialflags and pvs
5462                 p->materialflags = 0;
5463                 p->pvsvalid = false;
5464                 p->camera_entity = t->camera_entity;
5465                 VectorCopy(surface->mins, p->mins);
5466                 VectorCopy(surface->maxs, p->maxs);
5467         }
5468         else
5469         {
5470                 // merge mins/maxs
5471                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5472                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5473                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5474                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5475                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5476                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5477         }
5478         // merge this surface's materialflags into the waterplane
5479         p->materialflags |= t->currentmaterialflags;
5480         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5481         {
5482                 // merge this surface's PVS into the waterplane
5483                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5484                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5485                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5486                 {
5487                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5488                         p->pvsvalid = true;
5489                 }
5490         }
5491 }
5492
5493 static void R_Water_ProcessPlanes(void)
5494 {
5495         int myscissor[4];
5496         r_refdef_view_t originalview;
5497         r_refdef_view_t myview;
5498         int planeindex;
5499         r_waterstate_waterplane_t *p;
5500         vec3_t visorigin;
5501
5502         originalview = r_refdef.view;
5503
5504         // make sure enough textures are allocated
5505         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5506         {
5507                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5508                 {
5509                         if (!p->texture_refraction)
5510                                 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);
5511                         if (!p->texture_refraction)
5512                                 goto error;
5513                 }
5514                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5515                 {
5516                         if (!p->texture_camera)
5517                                 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);
5518                         if (!p->texture_camera)
5519                                 goto error;
5520                 }
5521
5522                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5523                 {
5524                         if (!p->texture_reflection)
5525                                 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);
5526                         if (!p->texture_reflection)
5527                                 goto error;
5528                 }
5529         }
5530
5531         // render views
5532         r_refdef.view = originalview;
5533         r_refdef.view.showdebug = false;
5534         r_refdef.view.width = r_waterstate.waterwidth;
5535         r_refdef.view.height = r_waterstate.waterheight;
5536         r_refdef.view.useclipplane = true;
5537         myview = r_refdef.view;
5538         r_waterstate.renderingscene = true;
5539         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5540         {
5541                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5542                 {
5543                         r_refdef.view = myview;
5544                         if(r_water_scissormode.integer)
5545                         {
5546                                 R_SetupView(true);
5547                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5548                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5549                         }
5550
5551                         // render reflected scene and copy into texture
5552                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5553                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5554                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5555                         r_refdef.view.clipplane = p->plane;
5556
5557                         // reverse the cullface settings for this render
5558                         r_refdef.view.cullface_front = GL_FRONT;
5559                         r_refdef.view.cullface_back = GL_BACK;
5560                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5561                         {
5562                                 r_refdef.view.usecustompvs = true;
5563                                 if (p->pvsvalid)
5564                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5565                                 else
5566                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5567                         }
5568
5569                         R_ResetViewRendering3D();
5570                         R_ClearScreen(r_refdef.fogenabled);
5571                         if(r_water_scissormode.integer & 2)
5572                                 R_View_UpdateWithScissor(myscissor);
5573                         else
5574                                 R_View_Update();
5575                         if(r_water_scissormode.integer & 1)
5576                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5577                         R_RenderScene();
5578
5579                         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);
5580                 }
5581
5582                 // render the normal view scene and copy into texture
5583                 // (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)
5584                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5585                 {
5586                         r_refdef.view = myview;
5587                         if(r_water_scissormode.integer)
5588                         {
5589                                 R_SetupView(true);
5590                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5591                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5592                         }
5593
5594                         r_waterstate.renderingrefraction = true;
5595
5596                         r_refdef.view.clipplane = p->plane;
5597                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5598                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5599
5600                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5601                         {
5602                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5603                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5604                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5605                                 R_RenderView_UpdateViewVectors();
5606                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5607                                 {
5608                                         r_refdef.view.usecustompvs = true;
5609                                         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);
5610                                 }
5611                         }
5612
5613                         PlaneClassify(&r_refdef.view.clipplane);
5614
5615                         R_ResetViewRendering3D();
5616                         R_ClearScreen(r_refdef.fogenabled);
5617                         if(r_water_scissormode.integer & 2)
5618                                 R_View_UpdateWithScissor(myscissor);
5619                         else
5620                                 R_View_Update();
5621                         if(r_water_scissormode.integer & 1)
5622                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5623                         R_RenderScene();
5624
5625                         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);
5626                         r_waterstate.renderingrefraction = false;
5627                 }
5628                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5629                 {
5630                         r_refdef.view = myview;
5631
5632                         r_refdef.view.clipplane = p->plane;
5633                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5634                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5635
5636                         r_refdef.view.width = r_waterstate.camerawidth;
5637                         r_refdef.view.height = r_waterstate.cameraheight;
5638                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5639                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5640
5641                         if(p->camera_entity)
5642                         {
5643                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5644                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5645                         }
5646
5647                         // note: all of the view is used for displaying... so
5648                         // there is no use in scissoring
5649
5650                         // reverse the cullface settings for this render
5651                         r_refdef.view.cullface_front = GL_FRONT;
5652                         r_refdef.view.cullface_back = GL_BACK;
5653                         // also reverse the view matrix
5654                         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
5655                         R_RenderView_UpdateViewVectors();
5656                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5657                         {
5658                                 r_refdef.view.usecustompvs = true;
5659                                 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);
5660                         }
5661                         
5662                         // camera needs no clipplane
5663                         r_refdef.view.useclipplane = false;
5664
5665                         PlaneClassify(&r_refdef.view.clipplane);
5666
5667                         R_ResetViewRendering3D();
5668                         R_ClearScreen(r_refdef.fogenabled);
5669                         R_View_Update();
5670                         R_RenderScene();
5671
5672                         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);
5673                         r_waterstate.renderingrefraction = false;
5674                 }
5675
5676         }
5677         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5678         r_waterstate.renderingscene = false;
5679         r_refdef.view = originalview;
5680         R_ResetViewRendering3D();
5681         R_ClearScreen(r_refdef.fogenabled);
5682         R_View_Update();
5683         return;
5684 error:
5685         r_refdef.view = originalview;
5686         r_waterstate.renderingscene = false;
5687         Cvar_SetValueQuick(&r_water, 0);
5688         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5689         return;
5690 }
5691
5692 void R_Bloom_StartFrame(void)
5693 {
5694         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5695         int viewwidth, viewheight;
5696         textype_t textype;
5697
5698         if (r_viewscale_fpsscaling.integer)
5699         {
5700                 double actualframetime;
5701                 double targetframetime;
5702                 double adjust;
5703                 actualframetime = r_refdef.lastdrawscreentime;
5704                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5705                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5706                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5707                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5708                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5709                 viewscalefpsadjusted += adjust;
5710                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5711         }
5712         else
5713                 viewscalefpsadjusted = 1.0f;
5714
5715         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5716
5717         switch(vid.renderpath)
5718         {
5719         case RENDERPATH_GL20:
5720         case RENDERPATH_D3D9:
5721         case RENDERPATH_D3D10:
5722         case RENDERPATH_D3D11:
5723         case RENDERPATH_SOFT:
5724         case RENDERPATH_GLES2:
5725                 break;
5726         case RENDERPATH_GL13:
5727         case RENDERPATH_GL11:
5728                 return;
5729         }
5730
5731         // set bloomwidth and bloomheight to the bloom resolution that will be
5732         // used (often less than the screen resolution for faster rendering)
5733         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5734         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5735         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5736         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5737         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5738
5739         // calculate desired texture sizes
5740         if (vid.support.arb_texture_non_power_of_two)
5741         {
5742                 screentexturewidth = vid.width;
5743                 screentextureheight = vid.height;
5744                 bloomtexturewidth = r_bloomstate.bloomwidth;
5745                 bloomtextureheight = r_bloomstate.bloomheight;
5746         }
5747         else
5748         {
5749                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5750                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5751                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5752                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5753         }
5754
5755         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))
5756         {
5757                 Cvar_SetValueQuick(&r_hdr, 0);
5758                 Cvar_SetValueQuick(&r_bloom, 0);
5759                 Cvar_SetValueQuick(&r_motionblur, 0);
5760                 Cvar_SetValueQuick(&r_damageblur, 0);
5761         }
5762
5763         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)
5764                 screentexturewidth = screentextureheight = 0;
5765         if (!r_hdr.integer && !r_bloom.integer)
5766                 bloomtexturewidth = bloomtextureheight = 0;
5767
5768         textype = TEXTYPE_COLORBUFFER;
5769         switch (vid.renderpath)
5770         {
5771         case RENDERPATH_GL20:
5772         case RENDERPATH_GLES2:
5773                 if (vid.support.ext_framebuffer_object)
5774                 {
5775                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5776                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5777                 }
5778                 break;
5779         case RENDERPATH_D3D9:
5780         case RENDERPATH_D3D10:
5781         case RENDERPATH_D3D11:
5782         case RENDERPATH_SOFT:
5783         case RENDERPATH_GL13:
5784         case RENDERPATH_GL11:
5785                 break;
5786         }
5787
5788         // allocate textures as needed
5789         if (r_bloomstate.screentexturewidth != screentexturewidth
5790          || r_bloomstate.screentextureheight != screentextureheight
5791          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5792          || r_bloomstate.bloomtextureheight != bloomtextureheight
5793          || r_bloomstate.texturetype != textype
5794          || r_bloomstate.viewfbo != r_viewfbo.integer)
5795         {
5796                 if (r_bloomstate.texture_bloom)
5797                         R_FreeTexture(r_bloomstate.texture_bloom);
5798                 r_bloomstate.texture_bloom = NULL;
5799                 if (r_bloomstate.texture_screen)
5800                         R_FreeTexture(r_bloomstate.texture_screen);
5801                 r_bloomstate.texture_screen = NULL;
5802                 if (r_bloomstate.fbo_framebuffer)
5803                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5804                 r_bloomstate.fbo_framebuffer = 0;
5805                 if (r_bloomstate.texture_framebuffercolor)
5806                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5807                 r_bloomstate.texture_framebuffercolor = NULL;
5808                 if (r_bloomstate.texture_framebufferdepth)
5809                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5810                 r_bloomstate.texture_framebufferdepth = NULL;
5811                 r_bloomstate.screentexturewidth = screentexturewidth;
5812                 r_bloomstate.screentextureheight = screentextureheight;
5813                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5814                         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);
5815                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5816                 {
5817                         // FIXME: choose depth bits based on a cvar
5818                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5819                         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);
5820                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5821                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5822                         // render depth into one texture and normalmap into the other
5823                         if (qglDrawBuffer)
5824                         {
5825                                 int status;
5826                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5827                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5828                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5829                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5830                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5831                         }
5832                 }
5833                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5834                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5835                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5836                         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);
5837                 r_bloomstate.viewfbo = r_viewfbo.integer;
5838                 r_bloomstate.texturetype = textype;
5839         }
5840
5841         // when doing a reduced render (HDR) we want to use a smaller area
5842         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5843         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5844         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5845         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5846         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5847
5848         // set up a texcoord array for the full resolution screen image
5849         // (we have to keep this around to copy back during final render)
5850         r_bloomstate.screentexcoord2f[0] = 0;
5851         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5852         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5853         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5854         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5855         r_bloomstate.screentexcoord2f[5] = 0;
5856         r_bloomstate.screentexcoord2f[6] = 0;
5857         r_bloomstate.screentexcoord2f[7] = 0;
5858
5859         // set up a texcoord array for the reduced resolution bloom image
5860         // (which will be additive blended over the screen image)
5861         r_bloomstate.bloomtexcoord2f[0] = 0;
5862         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5863         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5864         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5865         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5866         r_bloomstate.bloomtexcoord2f[5] = 0;
5867         r_bloomstate.bloomtexcoord2f[6] = 0;
5868         r_bloomstate.bloomtexcoord2f[7] = 0;
5869
5870         switch(vid.renderpath)
5871         {
5872         case RENDERPATH_GL11:
5873         case RENDERPATH_GL13:
5874         case RENDERPATH_GL20:
5875         case RENDERPATH_SOFT:
5876         case RENDERPATH_GLES2:
5877                 break;
5878         case RENDERPATH_D3D9:
5879         case RENDERPATH_D3D10:
5880         case RENDERPATH_D3D11:
5881                 {
5882                         int i;
5883                         for (i = 0;i < 4;i++)
5884                         {
5885                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5886                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5887                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5888                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5889                         }
5890                 }
5891                 break;
5892         }
5893
5894         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5895         {
5896                 r_bloomstate.enabled = true;
5897                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5898         }
5899
5900         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);
5901
5902         if (r_bloomstate.fbo_framebuffer)
5903                 r_refdef.view.clear = true;
5904 }
5905
5906 void R_Bloom_CopyBloomTexture(float colorscale)
5907 {
5908         r_refdef.stats.bloom++;
5909
5910         // scale down screen texture to the bloom texture size
5911         CHECKGLERROR
5912         R_Mesh_SetMainRenderTargets();
5913         R_SetViewport(&r_bloomstate.viewport);
5914         GL_BlendFunc(GL_ONE, GL_ZERO);
5915         GL_Color(colorscale, colorscale, colorscale, 1);
5916         // 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...
5917         switch(vid.renderpath)
5918         {
5919         case RENDERPATH_GL11:
5920         case RENDERPATH_GL13:
5921         case RENDERPATH_GL20:
5922         case RENDERPATH_SOFT:
5923         case RENDERPATH_GLES2:
5924                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5925                 break;
5926         case RENDERPATH_D3D9:
5927         case RENDERPATH_D3D10:
5928         case RENDERPATH_D3D11:
5929                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5930                 break;
5931         }
5932         // TODO: do boxfilter scale-down in shader?
5933         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5934         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5935         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5936
5937         // we now have a bloom image in the framebuffer
5938         // copy it into the bloom image texture for later processing
5939         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);
5940         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5941 }
5942
5943 void R_Bloom_CopyHDRTexture(void)
5944 {
5945         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);
5946         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5947 }
5948
5949 void R_Bloom_MakeTexture(void)
5950 {
5951         int x, range, dir;
5952         float xoffset, yoffset, r, brighten;
5953
5954         r_refdef.stats.bloom++;
5955
5956         R_ResetViewRendering2D();
5957
5958         // we have a bloom image in the framebuffer
5959         CHECKGLERROR
5960         R_SetViewport(&r_bloomstate.viewport);
5961
5962         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5963         {
5964                 x *= 2;
5965                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5966                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5967                 GL_Color(r,r,r,1);
5968                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5969                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5970                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5971                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5972
5973                 // copy the vertically blurred bloom view to a texture
5974                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5975                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5976         }
5977
5978         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5979         brighten = r_bloom_brighten.value;
5980         if (r_bloomstate.hdr)
5981                 brighten *= r_hdr_range.value;
5982         brighten = sqrt(brighten);
5983         if(range >= 1)
5984                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5985         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5986
5987         for (dir = 0;dir < 2;dir++)
5988         {
5989                 // blend on at multiple vertical offsets to achieve a vertical blur
5990                 // TODO: do offset blends using GLSL
5991                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5992                 GL_BlendFunc(GL_ONE, GL_ZERO);
5993                 for (x = -range;x <= range;x++)
5994                 {
5995                         if (!dir){xoffset = 0;yoffset = x;}
5996                         else {xoffset = x;yoffset = 0;}
5997                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5998                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5999                         // compute a texcoord array with the specified x and y offset
6000                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6001                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6002                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6003                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6004                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6005                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6006                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6007                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6008                         // this r value looks like a 'dot' particle, fading sharply to
6009                         // black at the edges
6010                         // (probably not realistic but looks good enough)
6011                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6012                         //r = brighten/(range*2+1);
6013                         r = brighten / (range * 2 + 1);
6014                         if(range >= 1)
6015                                 r *= (1 - x*x/(float)(range*range));
6016                         GL_Color(r, r, r, 1);
6017                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6018                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6019                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6020                         GL_BlendFunc(GL_ONE, GL_ONE);
6021                 }
6022
6023                 // copy the vertically blurred bloom view to a texture
6024                 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);
6025                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6026         }
6027 }
6028
6029 void R_HDR_RenderBloomTexture(void)
6030 {
6031         int oldwidth, oldheight;
6032         float oldcolorscale;
6033         qboolean oldwaterstate;
6034
6035         oldwaterstate = r_waterstate.enabled;
6036         oldcolorscale = r_refdef.view.colorscale;
6037         oldwidth = r_refdef.view.width;
6038         oldheight = r_refdef.view.height;
6039         r_refdef.view.width = r_bloomstate.bloomwidth;
6040         r_refdef.view.height = r_bloomstate.bloomheight;
6041
6042         if(r_hdr.integer < 2)
6043                 r_waterstate.enabled = false;
6044
6045         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6046         // TODO: add exposure compensation features
6047         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6048
6049         r_refdef.view.showdebug = false;
6050         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6051
6052         R_ResetViewRendering3D();
6053
6054         R_ClearScreen(r_refdef.fogenabled);
6055         if (r_timereport_active)
6056                 R_TimeReport("HDRclear");
6057
6058         R_View_Update();
6059         if (r_timereport_active)
6060                 R_TimeReport("visibility");
6061
6062         // only do secondary renders with HDR if r_hdr is 2 or higher
6063         r_waterstate.numwaterplanes = 0;
6064         if (r_waterstate.enabled)
6065                 R_RenderWaterPlanes();
6066
6067         r_refdef.view.showdebug = true;
6068         R_RenderScene();
6069         r_waterstate.numwaterplanes = 0;
6070
6071         R_ResetViewRendering2D();
6072
6073         R_Bloom_CopyHDRTexture();
6074         R_Bloom_MakeTexture();
6075
6076         // restore the view settings
6077         r_waterstate.enabled = oldwaterstate;
6078         r_refdef.view.width = oldwidth;
6079         r_refdef.view.height = oldheight;
6080         r_refdef.view.colorscale = oldcolorscale;
6081
6082         R_ResetViewRendering3D();
6083
6084         R_ClearScreen(r_refdef.fogenabled);
6085         if (r_timereport_active)
6086                 R_TimeReport("viewclear");
6087 }
6088
6089 static void R_BlendView(void)
6090 {
6091         unsigned int permutation;
6092         float uservecs[4][4];
6093
6094         switch (vid.renderpath)
6095         {
6096         case RENDERPATH_GL20:
6097         case RENDERPATH_D3D9:
6098         case RENDERPATH_D3D10:
6099         case RENDERPATH_D3D11:
6100         case RENDERPATH_SOFT:
6101         case RENDERPATH_GLES2:
6102                 permutation =
6103                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6104                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6105                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6106                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6107                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6108
6109                 if (r_bloomstate.texture_screen)
6110                 {
6111                         // make sure the buffer is available
6112                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6113
6114                         R_ResetViewRendering2D();
6115                         R_Mesh_SetMainRenderTargets();
6116
6117                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6118                         {
6119                                 // declare variables
6120                                 float speed;
6121                                 static float avgspeed;
6122
6123                                 speed = VectorLength(cl.movement_velocity);
6124
6125                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6126                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6127
6128                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6129                                 speed = bound(0, speed, 1);
6130                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6131
6132                                 // calculate values into a standard alpha
6133                                 cl.motionbluralpha = 1 - exp(-
6134                                                 (
6135                                                  (r_motionblur.value * speed / 80)
6136                                                  +
6137                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6138                                                 )
6139                                                 /
6140                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6141                                            );
6142
6143                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6144                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6145                                 // apply the blur
6146                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6147                                 {
6148                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6149                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6150                                         switch(vid.renderpath)
6151                                         {
6152                                         case RENDERPATH_GL11:
6153                                         case RENDERPATH_GL13:
6154                                         case RENDERPATH_GL20:
6155                                         case RENDERPATH_SOFT:
6156                                         case RENDERPATH_GLES2:
6157                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6158                                                 break;
6159                                         case RENDERPATH_D3D9:
6160                                         case RENDERPATH_D3D10:
6161                                         case RENDERPATH_D3D11:
6162                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6163                                                 break;
6164                                         }
6165                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6166                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6167                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6168                                 }
6169                         }
6170
6171                         // copy view into the screen texture
6172                         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);
6173                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6174                 }
6175                 else if (!r_bloomstate.texture_bloom)
6176                 {
6177                         // we may still have to do view tint...
6178                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6179                         {
6180                                 // apply a color tint to the whole view
6181                                 R_ResetViewRendering2D();
6182                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6183                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6184                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6185                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6186                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6187                         }
6188                         break; // no screen processing, no bloom, skip it
6189                 }
6190
6191                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6192                 {
6193                         // render simple bloom effect
6194                         // copy the screen and shrink it and darken it for the bloom process
6195                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6196                         // make the bloom texture
6197                         R_Bloom_MakeTexture();
6198                 }
6199
6200 #if _MSC_VER >= 1400
6201 #define sscanf sscanf_s
6202 #endif
6203                 memset(uservecs, 0, sizeof(uservecs));
6204                 if (r_glsl_postprocess_uservec1_enable.integer)
6205                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6206                 if (r_glsl_postprocess_uservec2_enable.integer)
6207                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6208                 if (r_glsl_postprocess_uservec3_enable.integer)
6209                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6210                 if (r_glsl_postprocess_uservec4_enable.integer)
6211                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6212
6213                 R_ResetViewRendering2D();
6214                 GL_Color(1, 1, 1, 1);
6215                 GL_BlendFunc(GL_ONE, GL_ZERO);
6216
6217                 switch(vid.renderpath)
6218                 {
6219                 case RENDERPATH_GL20:
6220                 case RENDERPATH_GLES2:
6221                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6222                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6223                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6224                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6225                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6226                         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]);
6227                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6228                         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]);
6229                         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]);
6230                         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]);
6231                         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]);
6232                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6233                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6234                         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);
6235                         break;
6236                 case RENDERPATH_D3D9:
6237 #ifdef SUPPORTD3D
6238                         // 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...
6239                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6240                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6241                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6242                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6243                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6244                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6245                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6246                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6247                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6248                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6249                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6250                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6251                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6252                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6253 #endif
6254                         break;
6255                 case RENDERPATH_D3D10:
6256                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6257                         break;
6258                 case RENDERPATH_D3D11:
6259                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6260                         break;
6261                 case RENDERPATH_SOFT:
6262                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6263                         R_SetupShader_SetPermutationSoft(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                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6268                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6269                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6270                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6271                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6272                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6273                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6274                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6275                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6276                         break;
6277                 default:
6278                         break;
6279                 }
6280                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6281                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6282                 break;
6283         case RENDERPATH_GL13:
6284         case RENDERPATH_GL11:
6285                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6286                 {
6287                         // apply a color tint to the whole view
6288                         R_ResetViewRendering2D();
6289                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6290                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6291                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6292                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6293                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6294                 }
6295                 break;
6296         }
6297 }
6298
6299 matrix4x4_t r_waterscrollmatrix;
6300
6301 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6302 {
6303         if (r_refdef.fog_density)
6304         {
6305                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6306                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6307                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6308
6309                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6310                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6311                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6312                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6313
6314                 {
6315                         vec3_t fogvec;
6316                         VectorCopy(r_refdef.fogcolor, fogvec);
6317                         //   color.rgb *= ContrastBoost * SceneBrightness;
6318                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6319                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6320                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6321                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6322                 }
6323         }
6324 }
6325
6326 void R_UpdateVariables(void)
6327 {
6328         R_Textures_Frame();
6329
6330         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6331
6332         r_refdef.farclip = r_farclip_base.value;
6333         if (r_refdef.scene.worldmodel)
6334                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6335         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6336
6337         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6338                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6339         r_refdef.polygonfactor = 0;
6340         r_refdef.polygonoffset = 0;
6341         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6342         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6343
6344         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6345         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6346         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6347         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6348         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6349         if (FAKELIGHT_ENABLED)
6350         {
6351                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6352         }
6353         if (r_showsurfaces.integer)
6354         {
6355                 r_refdef.scene.rtworld = false;
6356                 r_refdef.scene.rtworldshadows = false;
6357                 r_refdef.scene.rtdlight = false;
6358                 r_refdef.scene.rtdlightshadows = false;
6359                 r_refdef.lightmapintensity = 0;
6360         }
6361
6362         if (gamemode == GAME_NEHAHRA)
6363         {
6364                 if (gl_fogenable.integer)
6365                 {
6366                         r_refdef.oldgl_fogenable = true;
6367                         r_refdef.fog_density = gl_fogdensity.value;
6368                         r_refdef.fog_red = gl_fogred.value;
6369                         r_refdef.fog_green = gl_foggreen.value;
6370                         r_refdef.fog_blue = gl_fogblue.value;
6371                         r_refdef.fog_alpha = 1;
6372                         r_refdef.fog_start = 0;
6373                         r_refdef.fog_end = gl_skyclip.value;
6374                         r_refdef.fog_height = 1<<30;
6375                         r_refdef.fog_fadedepth = 128;
6376                 }
6377                 else if (r_refdef.oldgl_fogenable)
6378                 {
6379                         r_refdef.oldgl_fogenable = false;
6380                         r_refdef.fog_density = 0;
6381                         r_refdef.fog_red = 0;
6382                         r_refdef.fog_green = 0;
6383                         r_refdef.fog_blue = 0;
6384                         r_refdef.fog_alpha = 0;
6385                         r_refdef.fog_start = 0;
6386                         r_refdef.fog_end = 0;
6387                         r_refdef.fog_height = 1<<30;
6388                         r_refdef.fog_fadedepth = 128;
6389                 }
6390         }
6391
6392         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6393         r_refdef.fog_start = max(0, r_refdef.fog_start);
6394         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6395
6396         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6397
6398         if (r_refdef.fog_density && r_drawfog.integer)
6399         {
6400                 r_refdef.fogenabled = true;
6401                 // this is the point where the fog reaches 0.9986 alpha, which we
6402                 // consider a good enough cutoff point for the texture
6403                 // (0.9986 * 256 == 255.6)
6404                 if (r_fog_exp2.integer)
6405                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6406                 else
6407                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6408                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6409                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6410                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6411                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6412                         R_BuildFogHeightTexture();
6413                 // fog color was already set
6414                 // update the fog texture
6415                 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)
6416                         R_BuildFogTexture();
6417                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6418                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6419         }
6420         else
6421                 r_refdef.fogenabled = false;
6422
6423         switch(vid.renderpath)
6424         {
6425         case RENDERPATH_GL20:
6426         case RENDERPATH_D3D9:
6427         case RENDERPATH_D3D10:
6428         case RENDERPATH_D3D11:
6429         case RENDERPATH_SOFT:
6430         case RENDERPATH_GLES2:
6431                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6432                 {
6433                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6434                         {
6435                                 // build GLSL gamma texture
6436 #define RAMPWIDTH 256
6437                                 unsigned short ramp[RAMPWIDTH * 3];
6438                                 unsigned char rampbgr[RAMPWIDTH][4];
6439                                 int i;
6440
6441                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6442
6443                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6444                                 for(i = 0; i < RAMPWIDTH; ++i)
6445                                 {
6446                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6447                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6448                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6449                                         rampbgr[i][3] = 0;
6450                                 }
6451                                 if (r_texture_gammaramps)
6452                                 {
6453                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6454                                 }
6455                                 else
6456                                 {
6457                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6458                                 }
6459                         }
6460                 }
6461                 else
6462                 {
6463                         // remove GLSL gamma texture
6464                 }
6465                 break;
6466         case RENDERPATH_GL13:
6467         case RENDERPATH_GL11:
6468                 break;
6469         }
6470 }
6471
6472 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6473 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6474 /*
6475 ================
6476 R_SelectScene
6477 ================
6478 */
6479 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6480         if( scenetype != r_currentscenetype ) {
6481                 // store the old scenetype
6482                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6483                 r_currentscenetype = scenetype;
6484                 // move in the new scene
6485                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6486         }
6487 }
6488
6489 /*
6490 ================
6491 R_GetScenePointer
6492 ================
6493 */
6494 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6495 {
6496         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6497         if( scenetype == r_currentscenetype ) {
6498                 return &r_refdef.scene;
6499         } else {
6500                 return &r_scenes_store[ scenetype ];
6501         }
6502 }
6503
6504 /*
6505 ================
6506 R_RenderView
6507 ================
6508 */
6509 int dpsoftrast_test;
6510 void R_RenderView(void)
6511 {
6512         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6513
6514         dpsoftrast_test = r_test.integer;
6515
6516         if (r_timereport_active)
6517                 R_TimeReport("start");
6518         r_textureframe++; // used only by R_GetCurrentTexture
6519         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6520
6521         if(R_CompileShader_CheckStaticParms())
6522                 R_GLSL_Restart_f();
6523
6524         if (!r_drawentities.integer)
6525                 r_refdef.scene.numentities = 0;
6526
6527         R_AnimCache_ClearCache();
6528         R_FrameData_NewFrame();
6529
6530         /* adjust for stereo display */
6531         if(R_Stereo_Active())
6532         {
6533                 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);
6534                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6535         }
6536
6537         if (r_refdef.view.isoverlay)
6538         {
6539                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6540                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6541                 R_TimeReport("depthclear");
6542
6543                 r_refdef.view.showdebug = false;
6544
6545                 r_waterstate.enabled = false;
6546                 r_waterstate.numwaterplanes = 0;
6547
6548                 R_RenderScene();
6549
6550                 r_refdef.view.matrix = originalmatrix;
6551
6552                 CHECKGLERROR
6553                 return;
6554         }
6555
6556         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6557         {
6558                 r_refdef.view.matrix = originalmatrix;
6559                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6560         }
6561
6562         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6563
6564         R_RenderView_UpdateViewVectors();
6565
6566         R_Shadow_UpdateWorldLightSelection();
6567
6568         R_Bloom_StartFrame();
6569         R_Water_StartFrame();
6570
6571         CHECKGLERROR
6572         if (r_timereport_active)
6573                 R_TimeReport("viewsetup");
6574
6575         R_ResetViewRendering3D();
6576
6577         if (r_refdef.view.clear || r_refdef.fogenabled)
6578         {
6579                 R_ClearScreen(r_refdef.fogenabled);
6580                 if (r_timereport_active)
6581                         R_TimeReport("viewclear");
6582         }
6583         r_refdef.view.clear = true;
6584
6585         // this produces a bloom texture to be used in R_BlendView() later
6586         if (r_bloomstate.hdr)
6587         {
6588                 R_HDR_RenderBloomTexture();
6589                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6590                 r_textureframe++; // used only by R_GetCurrentTexture
6591         }
6592
6593         r_refdef.view.showdebug = true;
6594
6595         R_View_Update();
6596         if (r_timereport_active)
6597                 R_TimeReport("visibility");
6598
6599         r_waterstate.numwaterplanes = 0;
6600         if (r_waterstate.enabled)
6601                 R_RenderWaterPlanes();
6602
6603         R_RenderScene();
6604         r_waterstate.numwaterplanes = 0;
6605
6606         R_BlendView();
6607         if (r_timereport_active)
6608                 R_TimeReport("blendview");
6609
6610         GL_Scissor(0, 0, vid.width, vid.height);
6611         GL_ScissorTest(false);
6612
6613         r_refdef.view.matrix = originalmatrix;
6614
6615         CHECKGLERROR
6616 }
6617
6618 void R_RenderWaterPlanes(void)
6619 {
6620         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6621         {
6622                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6623                 if (r_timereport_active)
6624                         R_TimeReport("waterworld");
6625         }
6626
6627         // don't let sound skip if going slow
6628         if (r_refdef.scene.extraupdate)
6629                 S_ExtraUpdate ();
6630
6631         R_DrawModelsAddWaterPlanes();
6632         if (r_timereport_active)
6633                 R_TimeReport("watermodels");
6634
6635         if (r_waterstate.numwaterplanes)
6636         {
6637                 R_Water_ProcessPlanes();
6638                 if (r_timereport_active)
6639                         R_TimeReport("waterscenes");
6640         }
6641 }
6642
6643 extern void R_DrawLightningBeams (void);
6644 extern void VM_CL_AddPolygonsToMeshQueue (void);
6645 extern void R_DrawPortals (void);
6646 extern cvar_t cl_locs_show;
6647 static void R_DrawLocs(void);
6648 static void R_DrawEntityBBoxes(void);
6649 static void R_DrawModelDecals(void);
6650 extern void R_DrawModelShadows(void);
6651 extern void R_DrawModelShadowMaps(void);
6652 extern cvar_t cl_decals_newsystem;
6653 extern qboolean r_shadow_usingdeferredprepass;
6654 void R_RenderScene(void)
6655 {
6656         qboolean shadowmapping = false;
6657
6658         if (r_timereport_active)
6659                 R_TimeReport("beginscene");
6660
6661         r_refdef.stats.renders++;
6662
6663         R_UpdateFogColor();
6664
6665         // don't let sound skip if going slow
6666         if (r_refdef.scene.extraupdate)
6667                 S_ExtraUpdate ();
6668
6669         R_MeshQueue_BeginScene();
6670
6671         R_SkyStartFrame();
6672
6673         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);
6674
6675         if (r_timereport_active)
6676                 R_TimeReport("skystartframe");
6677
6678         if (cl.csqc_vidvars.drawworld)
6679         {
6680                 // don't let sound skip if going slow
6681                 if (r_refdef.scene.extraupdate)
6682                         S_ExtraUpdate ();
6683
6684                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6685                 {
6686                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6687                         if (r_timereport_active)
6688                                 R_TimeReport("worldsky");
6689                 }
6690
6691                 if (R_DrawBrushModelsSky() && r_timereport_active)
6692                         R_TimeReport("bmodelsky");
6693
6694                 if (skyrendermasked && skyrenderlater)
6695                 {
6696                         // we have to force off the water clipping plane while rendering sky
6697                         R_SetupView(false);
6698                         R_Sky();
6699                         R_SetupView(true);
6700                         if (r_timereport_active)
6701                                 R_TimeReport("sky");
6702                 }
6703         }
6704
6705         R_AnimCache_CacheVisibleEntities();
6706         if (r_timereport_active)
6707                 R_TimeReport("animation");
6708
6709         R_Shadow_PrepareLights();
6710         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6711                 R_Shadow_PrepareModelShadows();
6712         if (r_timereport_active)
6713                 R_TimeReport("preparelights");
6714
6715         if (R_Shadow_ShadowMappingEnabled())
6716                 shadowmapping = true;
6717
6718         if (r_shadow_usingdeferredprepass)
6719                 R_Shadow_DrawPrepass();
6720
6721         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6722         {
6723                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6724                 if (r_timereport_active)
6725                         R_TimeReport("worlddepth");
6726         }
6727         if (r_depthfirst.integer >= 2)
6728         {
6729                 R_DrawModelsDepth();
6730                 if (r_timereport_active)
6731                         R_TimeReport("modeldepth");
6732         }
6733
6734         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6735         {
6736                 R_DrawModelShadowMaps();
6737                 R_ResetViewRendering3D();
6738                 // don't let sound skip if going slow
6739                 if (r_refdef.scene.extraupdate)
6740                         S_ExtraUpdate ();
6741         }
6742
6743         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6744         {
6745                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6746                 if (r_timereport_active)
6747                         R_TimeReport("world");
6748         }
6749
6750         // don't let sound skip if going slow
6751         if (r_refdef.scene.extraupdate)
6752                 S_ExtraUpdate ();
6753
6754         R_DrawModels();
6755         if (r_timereport_active)
6756                 R_TimeReport("models");
6757
6758         // don't let sound skip if going slow
6759         if (r_refdef.scene.extraupdate)
6760                 S_ExtraUpdate ();
6761
6762         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6763         {
6764                 R_DrawModelShadows();
6765                 R_ResetViewRendering3D();
6766                 // don't let sound skip if going slow
6767                 if (r_refdef.scene.extraupdate)
6768                         S_ExtraUpdate ();
6769         }
6770
6771         if (!r_shadow_usingdeferredprepass)
6772         {
6773                 R_Shadow_DrawLights();
6774                 if (r_timereport_active)
6775                         R_TimeReport("rtlights");
6776         }
6777
6778         // don't let sound skip if going slow
6779         if (r_refdef.scene.extraupdate)
6780                 S_ExtraUpdate ();
6781
6782         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6783         {
6784                 R_DrawModelShadows();
6785                 R_ResetViewRendering3D();
6786                 // don't let sound skip if going slow
6787                 if (r_refdef.scene.extraupdate)
6788                         S_ExtraUpdate ();
6789         }
6790
6791         if (cl.csqc_vidvars.drawworld)
6792         {
6793                 if (cl_decals_newsystem.integer)
6794                 {
6795                         R_DrawModelDecals();
6796                         if (r_timereport_active)
6797                                 R_TimeReport("modeldecals");
6798                 }
6799                 else
6800                 {
6801                         R_DrawDecals();
6802                         if (r_timereport_active)
6803                                 R_TimeReport("decals");
6804                 }
6805
6806                 R_DrawParticles();
6807                 if (r_timereport_active)
6808                         R_TimeReport("particles");
6809
6810                 R_DrawExplosions();
6811                 if (r_timereport_active)
6812                         R_TimeReport("explosions");
6813
6814                 R_DrawLightningBeams();
6815                 if (r_timereport_active)
6816                         R_TimeReport("lightning");
6817         }
6818
6819         VM_CL_AddPolygonsToMeshQueue();
6820
6821         if (r_refdef.view.showdebug)
6822         {
6823                 if (cl_locs_show.integer)
6824                 {
6825                         R_DrawLocs();
6826                         if (r_timereport_active)
6827                                 R_TimeReport("showlocs");
6828                 }
6829
6830                 if (r_drawportals.integer)
6831                 {
6832                         R_DrawPortals();
6833                         if (r_timereport_active)
6834                                 R_TimeReport("portals");
6835                 }
6836
6837                 if (r_showbboxes.value > 0)
6838                 {
6839                         R_DrawEntityBBoxes();
6840                         if (r_timereport_active)
6841                                 R_TimeReport("bboxes");
6842                 }
6843         }
6844
6845         R_MeshQueue_RenderTransparent();
6846         if (r_timereport_active)
6847                 R_TimeReport("drawtrans");
6848
6849         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))
6850         {
6851                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6852                 if (r_timereport_active)
6853                         R_TimeReport("worlddebug");
6854                 R_DrawModelsDebug();
6855                 if (r_timereport_active)
6856                         R_TimeReport("modeldebug");
6857         }
6858
6859         if (cl.csqc_vidvars.drawworld)
6860         {
6861                 R_Shadow_DrawCoronas();
6862                 if (r_timereport_active)
6863                         R_TimeReport("coronas");
6864         }
6865
6866 #if 0
6867         {
6868                 GL_DepthTest(false);
6869                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6870                 GL_Color(1, 1, 1, 1);
6871                 qglBegin(GL_POLYGON);
6872                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6873                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6874                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6875                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6876                 qglEnd();
6877                 qglBegin(GL_POLYGON);
6878                 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]);
6879                 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]);
6880                 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]);
6881                 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]);
6882                 qglEnd();
6883                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6884         }
6885 #endif
6886
6887         // don't let sound skip if going slow
6888         if (r_refdef.scene.extraupdate)
6889                 S_ExtraUpdate ();
6890
6891         R_ResetViewRendering2D();
6892 }
6893
6894 static const unsigned short bboxelements[36] =
6895 {
6896         5, 1, 3, 5, 3, 7,
6897         6, 2, 0, 6, 0, 4,
6898         7, 3, 2, 7, 2, 6,
6899         4, 0, 1, 4, 1, 5,
6900         4, 5, 7, 4, 7, 6,
6901         1, 0, 2, 1, 2, 3,
6902 };
6903
6904 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6905 {
6906         int i;
6907         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6908
6909         RSurf_ActiveWorldEntity();
6910
6911         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6912         GL_DepthMask(false);
6913         GL_DepthRange(0, 1);
6914         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6915 //      R_Mesh_ResetTextureState();
6916
6917         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6918         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6919         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6920         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6921         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6922         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6923         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6924         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6925         R_FillColors(color4f, 8, cr, cg, cb, ca);
6926         if (r_refdef.fogenabled)
6927         {
6928                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6929                 {
6930                         f1 = RSurf_FogVertex(v);
6931                         f2 = 1 - f1;
6932                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6933                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6934                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6935                 }
6936         }
6937         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6938         R_Mesh_ResetTextureState();
6939         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6940         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6941 }
6942
6943 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6944 {
6945         int i;
6946         float color[4];
6947         prvm_edict_t *edict;
6948         prvm_prog_t *prog_save = prog;
6949
6950         // this function draws bounding boxes of server entities
6951         if (!sv.active)
6952                 return;
6953
6954         GL_CullFace(GL_NONE);
6955         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6956
6957         prog = 0;
6958         SV_VM_Begin();
6959         for (i = 0;i < numsurfaces;i++)
6960         {
6961                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6962                 switch ((int)edict->fields.server->solid)
6963                 {
6964                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6965                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6966                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6967                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6968                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6969                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6970                 }
6971                 color[3] *= r_showbboxes.value;
6972                 color[3] = bound(0, color[3], 1);
6973                 GL_DepthTest(!r_showdisabledepthtest.integer);
6974                 GL_CullFace(r_refdef.view.cullface_front);
6975                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6976         }
6977         SV_VM_End();
6978         prog = prog_save;
6979 }
6980
6981 static void R_DrawEntityBBoxes(void)
6982 {
6983         int i;
6984         prvm_edict_t *edict;
6985         vec3_t center;
6986         prvm_prog_t *prog_save = prog;
6987
6988         // this function draws bounding boxes of server entities
6989         if (!sv.active)
6990                 return;
6991
6992         prog = 0;
6993         SV_VM_Begin();
6994         for (i = 0;i < prog->num_edicts;i++)
6995         {
6996                 edict = PRVM_EDICT_NUM(i);
6997                 if (edict->priv.server->free)
6998                         continue;
6999                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7000                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7001                         continue;
7002                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7003                         continue;
7004                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7005                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7006         }
7007         SV_VM_End();
7008         prog = prog_save;
7009 }
7010
7011 static const int nomodelelement3i[24] =
7012 {
7013         5, 2, 0,
7014         5, 1, 2,
7015         5, 0, 3,
7016         5, 3, 1,
7017         0, 2, 4,
7018         2, 1, 4,
7019         3, 0, 4,
7020         1, 3, 4
7021 };
7022
7023 static const unsigned short nomodelelement3s[24] =
7024 {
7025         5, 2, 0,
7026         5, 1, 2,
7027         5, 0, 3,
7028         5, 3, 1,
7029         0, 2, 4,
7030         2, 1, 4,
7031         3, 0, 4,
7032         1, 3, 4
7033 };
7034
7035 static const float nomodelvertex3f[6*3] =
7036 {
7037         -16,   0,   0,
7038          16,   0,   0,
7039           0, -16,   0,
7040           0,  16,   0,
7041           0,   0, -16,
7042           0,   0,  16
7043 };
7044
7045 static const float nomodelcolor4f[6*4] =
7046 {
7047         0.0f, 0.0f, 0.5f, 1.0f,
7048         0.0f, 0.0f, 0.5f, 1.0f,
7049         0.0f, 0.5f, 0.0f, 1.0f,
7050         0.0f, 0.5f, 0.0f, 1.0f,
7051         0.5f, 0.0f, 0.0f, 1.0f,
7052         0.5f, 0.0f, 0.0f, 1.0f
7053 };
7054
7055 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7056 {
7057         int i;
7058         float f1, f2, *c;
7059         float color4f[6*4];
7060
7061         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);
7062
7063         // this is only called once per entity so numsurfaces is always 1, and
7064         // surfacelist is always {0}, so this code does not handle batches
7065
7066         if (rsurface.ent_flags & RENDER_ADDITIVE)
7067         {
7068                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7069                 GL_DepthMask(false);
7070         }
7071         else if (rsurface.colormod[3] < 1)
7072         {
7073                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7074                 GL_DepthMask(false);
7075         }
7076         else
7077         {
7078                 GL_BlendFunc(GL_ONE, GL_ZERO);
7079                 GL_DepthMask(true);
7080         }
7081         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7082         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7083         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7084         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7085         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7086         for (i = 0, c = color4f;i < 6;i++, c += 4)
7087         {
7088                 c[0] *= rsurface.colormod[0];
7089                 c[1] *= rsurface.colormod[1];
7090                 c[2] *= rsurface.colormod[2];
7091                 c[3] *= rsurface.colormod[3];
7092         }
7093         if (r_refdef.fogenabled)
7094         {
7095                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7096                 {
7097                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7098                         f2 = 1 - f1;
7099                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7100                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7101                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7102                 }
7103         }
7104 //      R_Mesh_ResetTextureState();
7105         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7106         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7107         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7108 }
7109
7110 void R_DrawNoModel(entity_render_t *ent)
7111 {
7112         vec3_t org;
7113         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7114         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7115                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7116         else
7117                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7118 }
7119
7120 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7121 {
7122         vec3_t right1, right2, diff, normal;
7123
7124         VectorSubtract (org2, org1, normal);
7125
7126         // calculate 'right' vector for start
7127         VectorSubtract (r_refdef.view.origin, org1, diff);
7128         CrossProduct (normal, diff, right1);
7129         VectorNormalize (right1);
7130
7131         // calculate 'right' vector for end
7132         VectorSubtract (r_refdef.view.origin, org2, diff);
7133         CrossProduct (normal, diff, right2);
7134         VectorNormalize (right2);
7135
7136         vert[ 0] = org1[0] + width * right1[0];
7137         vert[ 1] = org1[1] + width * right1[1];
7138         vert[ 2] = org1[2] + width * right1[2];
7139         vert[ 3] = org1[0] - width * right1[0];
7140         vert[ 4] = org1[1] - width * right1[1];
7141         vert[ 5] = org1[2] - width * right1[2];
7142         vert[ 6] = org2[0] - width * right2[0];
7143         vert[ 7] = org2[1] - width * right2[1];
7144         vert[ 8] = org2[2] - width * right2[2];
7145         vert[ 9] = org2[0] + width * right2[0];
7146         vert[10] = org2[1] + width * right2[1];
7147         vert[11] = org2[2] + width * right2[2];
7148 }
7149
7150 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)
7151 {
7152         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7153         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7154         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7155         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7156         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7157         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7158         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7159         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7160         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7161         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7162         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7163         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7164 }
7165
7166 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7167 {
7168         int i;
7169         float *vertex3f;
7170         float v[3];
7171         VectorSet(v, x, y, z);
7172         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7173                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7174                         break;
7175         if (i == mesh->numvertices)
7176         {
7177                 if (mesh->numvertices < mesh->maxvertices)
7178                 {
7179                         VectorCopy(v, vertex3f);
7180                         mesh->numvertices++;
7181                 }
7182                 return mesh->numvertices;
7183         }
7184         else
7185                 return i;
7186 }
7187
7188 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7189 {
7190         int i;
7191         int *e, element[3];
7192         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7193         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7194         e = mesh->element3i + mesh->numtriangles * 3;
7195         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7196         {
7197                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7198                 if (mesh->numtriangles < mesh->maxtriangles)
7199                 {
7200                         *e++ = element[0];
7201                         *e++ = element[1];
7202                         *e++ = element[2];
7203                         mesh->numtriangles++;
7204                 }
7205                 element[1] = element[2];
7206         }
7207 }
7208
7209 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7210 {
7211         int i;
7212         int *e, element[3];
7213         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7214         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7215         e = mesh->element3i + mesh->numtriangles * 3;
7216         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7217         {
7218                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7219                 if (mesh->numtriangles < mesh->maxtriangles)
7220                 {
7221                         *e++ = element[0];
7222                         *e++ = element[1];
7223                         *e++ = element[2];
7224                         mesh->numtriangles++;
7225                 }
7226                 element[1] = element[2];
7227         }
7228 }
7229
7230 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7231 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7232 {
7233         int planenum, planenum2;
7234         int w;
7235         int tempnumpoints;
7236         mplane_t *plane, *plane2;
7237         double maxdist;
7238         double temppoints[2][256*3];
7239         // figure out how large a bounding box we need to properly compute this brush
7240         maxdist = 0;
7241         for (w = 0;w < numplanes;w++)
7242                 maxdist = max(maxdist, fabs(planes[w].dist));
7243         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7244         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7245         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7246         {
7247                 w = 0;
7248                 tempnumpoints = 4;
7249                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7250                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7251                 {
7252                         if (planenum2 == planenum)
7253                                 continue;
7254                         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);
7255                         w = !w;
7256                 }
7257                 if (tempnumpoints < 3)
7258                         continue;
7259                 // generate elements forming a triangle fan for this polygon
7260                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7261         }
7262 }
7263
7264 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)
7265 {
7266         texturelayer_t *layer;
7267         layer = t->currentlayers + t->currentnumlayers++;
7268         layer->type = type;
7269         layer->depthmask = depthmask;
7270         layer->blendfunc1 = blendfunc1;
7271         layer->blendfunc2 = blendfunc2;
7272         layer->texture = texture;
7273         layer->texmatrix = *matrix;
7274         layer->color[0] = r;
7275         layer->color[1] = g;
7276         layer->color[2] = b;
7277         layer->color[3] = a;
7278 }
7279
7280 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7281 {
7282         if(parms[0] == 0 && parms[1] == 0)
7283                 return false;
7284         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7285                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7286                         return false;
7287         return true;
7288 }
7289
7290 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7291 {
7292         double index, f;
7293         index = parms[2] + r_refdef.scene.time * parms[3];
7294         index -= floor(index);
7295         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7296         {
7297         default:
7298         case Q3WAVEFUNC_NONE:
7299         case Q3WAVEFUNC_NOISE:
7300         case Q3WAVEFUNC_COUNT:
7301                 f = 0;
7302                 break;
7303         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7304         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7305         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7306         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7307         case Q3WAVEFUNC_TRIANGLE:
7308                 index *= 4;
7309                 f = index - floor(index);
7310                 if (index < 1)
7311                         f = f;
7312                 else if (index < 2)
7313                         f = 1 - f;
7314                 else if (index < 3)
7315                         f = -f;
7316                 else
7317                         f = -(1 - f);
7318                 break;
7319         }
7320         f = parms[0] + parms[1] * f;
7321         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7322                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7323         return (float) f;
7324 }
7325
7326 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7327 {
7328         int w, h, idx;
7329         float f;
7330         float tcmat[12];
7331         matrix4x4_t matrix, temp;
7332         switch(tcmod->tcmod)
7333         {
7334                 case Q3TCMOD_COUNT:
7335                 case Q3TCMOD_NONE:
7336                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7337                                 matrix = r_waterscrollmatrix;
7338                         else
7339                                 matrix = identitymatrix;
7340                         break;
7341                 case Q3TCMOD_ENTITYTRANSLATE:
7342                         // this is used in Q3 to allow the gamecode to control texcoord
7343                         // scrolling on the entity, which is not supported in darkplaces yet.
7344                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7345                         break;
7346                 case Q3TCMOD_ROTATE:
7347                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7348                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7349                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7350                         break;
7351                 case Q3TCMOD_SCALE:
7352                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7353                         break;
7354                 case Q3TCMOD_SCROLL:
7355                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7356                         break;
7357                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7358                         w = (int) tcmod->parms[0];
7359                         h = (int) tcmod->parms[1];
7360                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7361                         f = f - floor(f);
7362                         idx = (int) floor(f * w * h);
7363                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7364                         break;
7365                 case Q3TCMOD_STRETCH:
7366                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7367                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7368                         break;
7369                 case Q3TCMOD_TRANSFORM:
7370                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7371                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7372                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7373                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7374                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7375                         break;
7376                 case Q3TCMOD_TURBULENT:
7377                         // this is handled in the RSurf_PrepareVertices function
7378                         matrix = identitymatrix;
7379                         break;
7380         }
7381         temp = *texmatrix;
7382         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7383 }
7384
7385 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7386 {
7387         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7388         char name[MAX_QPATH];
7389         skinframe_t *skinframe;
7390         unsigned char pixels[296*194];
7391         strlcpy(cache->name, skinname, sizeof(cache->name));
7392         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7393         if (developer_loading.integer)
7394                 Con_Printf("loading %s\n", name);
7395         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7396         if (!skinframe || !skinframe->base)
7397         {
7398                 unsigned char *f;
7399                 fs_offset_t filesize;
7400                 skinframe = NULL;
7401                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7402                 if (f)
7403                 {
7404                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7405                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7406                         Mem_Free(f);
7407                 }
7408         }
7409         cache->skinframe = skinframe;
7410 }
7411
7412 texture_t *R_GetCurrentTexture(texture_t *t)
7413 {
7414         int i;
7415         const entity_render_t *ent = rsurface.entity;
7416         dp_model_t *model = ent->model;
7417         q3shaderinfo_layer_tcmod_t *tcmod;
7418
7419         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7420                 return t->currentframe;
7421         t->update_lastrenderframe = r_textureframe;
7422         t->update_lastrenderentity = (void *)ent;
7423
7424         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7425                 t->camera_entity = ent->entitynumber;
7426         else
7427                 t->camera_entity = 0;
7428
7429         // switch to an alternate material if this is a q1bsp animated material
7430         {
7431                 texture_t *texture = t;
7432                 int s = rsurface.ent_skinnum;
7433                 if ((unsigned int)s >= (unsigned int)model->numskins)
7434                         s = 0;
7435                 if (model->skinscenes)
7436                 {
7437                         if (model->skinscenes[s].framecount > 1)
7438                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7439                         else
7440                                 s = model->skinscenes[s].firstframe;
7441                 }
7442                 if (s > 0)
7443                         t = t + s * model->num_surfaces;
7444                 if (t->animated)
7445                 {
7446                         // use an alternate animation if the entity's frame is not 0,
7447                         // and only if the texture has an alternate animation
7448                         if (rsurface.ent_alttextures && t->anim_total[1])
7449                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7450                         else
7451                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7452                 }
7453                 texture->currentframe = t;
7454         }
7455
7456         // update currentskinframe to be a qw skin or animation frame
7457         if (rsurface.ent_qwskin >= 0)
7458         {
7459                 i = rsurface.ent_qwskin;
7460                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7461                 {
7462                         r_qwskincache_size = cl.maxclients;
7463                         if (r_qwskincache)
7464                                 Mem_Free(r_qwskincache);
7465                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7466                 }
7467                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7468                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7469                 t->currentskinframe = r_qwskincache[i].skinframe;
7470                 if (t->currentskinframe == NULL)
7471                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7472         }
7473         else if (t->numskinframes >= 2)
7474                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7475         if (t->backgroundnumskinframes >= 2)
7476                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7477
7478         t->currentmaterialflags = t->basematerialflags;
7479         t->currentalpha = rsurface.colormod[3];
7480         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7481                 t->currentalpha *= r_wateralpha.value;
7482         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7483                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7484         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7485                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7486         if (!(rsurface.ent_flags & RENDER_LIGHT))
7487                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7488         else if (FAKELIGHT_ENABLED)
7489         {
7490                         // no modellight if using fakelight for the map
7491         }
7492         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7493         {
7494                 // pick a model lighting mode
7495                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7496                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7497                 else
7498                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7499         }
7500         if (rsurface.ent_flags & RENDER_ADDITIVE)
7501                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7502         else if (t->currentalpha < 1)
7503                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7504         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7505                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7506         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7507                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7508         if (t->backgroundnumskinframes)
7509                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7510         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7511         {
7512                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7513                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7514         }
7515         else
7516                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7517         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7518                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7519
7520         // there is no tcmod
7521         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7522         {
7523                 t->currenttexmatrix = r_waterscrollmatrix;
7524                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7525         }
7526         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7527         {
7528                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7529                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7530         }
7531
7532         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7533                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7534         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7535                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7536
7537         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7538         if (t->currentskinframe->qpixels)
7539                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7540         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7541         if (!t->basetexture)
7542                 t->basetexture = r_texture_notexture;
7543         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7544         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7545         t->nmaptexture = t->currentskinframe->nmap;
7546         if (!t->nmaptexture)
7547                 t->nmaptexture = r_texture_blanknormalmap;
7548         t->glosstexture = r_texture_black;
7549         t->glowtexture = t->currentskinframe->glow;
7550         t->fogtexture = t->currentskinframe->fog;
7551         t->reflectmasktexture = t->currentskinframe->reflect;
7552         if (t->backgroundnumskinframes)
7553         {
7554                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7555                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7556                 t->backgroundglosstexture = r_texture_black;
7557                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7558                 if (!t->backgroundnmaptexture)
7559                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7560         }
7561         else
7562         {
7563                 t->backgroundbasetexture = r_texture_white;
7564                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7565                 t->backgroundglosstexture = r_texture_black;
7566                 t->backgroundglowtexture = NULL;
7567         }
7568         t->specularpower = r_shadow_glossexponent.value;
7569         // TODO: store reference values for these in the texture?
7570         t->specularscale = 0;
7571         if (r_shadow_gloss.integer > 0)
7572         {
7573                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7574                 {
7575                         if (r_shadow_glossintensity.value > 0)
7576                         {
7577                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7578                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7579                                 t->specularscale = r_shadow_glossintensity.value;
7580                         }
7581                 }
7582                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7583                 {
7584                         t->glosstexture = r_texture_white;
7585                         t->backgroundglosstexture = r_texture_white;
7586                         t->specularscale = r_shadow_gloss2intensity.value;
7587                         t->specularpower = r_shadow_gloss2exponent.value;
7588                 }
7589         }
7590         t->specularscale *= t->specularscalemod;
7591         t->specularpower *= t->specularpowermod;
7592
7593         // lightmaps mode looks bad with dlights using actual texturing, so turn
7594         // off the colormap and glossmap, but leave the normalmap on as it still
7595         // accurately represents the shading involved
7596         if (gl_lightmaps.integer)
7597         {
7598                 t->basetexture = r_texture_grey128;
7599                 t->pantstexture = r_texture_black;
7600                 t->shirttexture = r_texture_black;
7601                 t->nmaptexture = r_texture_blanknormalmap;
7602                 t->glosstexture = r_texture_black;
7603                 t->glowtexture = NULL;
7604                 t->fogtexture = NULL;
7605                 t->reflectmasktexture = NULL;
7606                 t->backgroundbasetexture = NULL;
7607                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7608                 t->backgroundglosstexture = r_texture_black;
7609                 t->backgroundglowtexture = NULL;
7610                 t->specularscale = 0;
7611                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7612         }
7613
7614         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7615         VectorClear(t->dlightcolor);
7616         t->currentnumlayers = 0;
7617         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7618         {
7619                 int blendfunc1, blendfunc2;
7620                 qboolean depthmask;
7621                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7622                 {
7623                         blendfunc1 = GL_SRC_ALPHA;
7624                         blendfunc2 = GL_ONE;
7625                 }
7626                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7627                 {
7628                         blendfunc1 = GL_SRC_ALPHA;
7629                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7630                 }
7631                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7632                 {
7633                         blendfunc1 = t->customblendfunc[0];
7634                         blendfunc2 = t->customblendfunc[1];
7635                 }
7636                 else
7637                 {
7638                         blendfunc1 = GL_ONE;
7639                         blendfunc2 = GL_ZERO;
7640                 }
7641                 // don't colormod evilblend textures
7642                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7643                         VectorSet(t->lightmapcolor, 1, 1, 1);
7644                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7645                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7646                 {
7647                         // fullbright is not affected by r_refdef.lightmapintensity
7648                         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]);
7649                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7650                                 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]);
7651                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7652                                 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]);
7653                 }
7654                 else
7655                 {
7656                         vec3_t ambientcolor;
7657                         float colorscale;
7658                         // set the color tint used for lights affecting this surface
7659                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7660                         colorscale = 2;
7661                         // q3bsp has no lightmap updates, so the lightstylevalue that
7662                         // would normally be baked into the lightmap must be
7663                         // applied to the color
7664                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7665                         if (model->type == mod_brushq3)
7666                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7667                         colorscale *= r_refdef.lightmapintensity;
7668                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7669                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7670                         // basic lit geometry
7671                         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]);
7672                         // add pants/shirt if needed
7673                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7674                                 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]);
7675                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7676                                 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]);
7677                         // now add ambient passes if needed
7678                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7679                         {
7680                                 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]);
7681                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7682                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
7683                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7684                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
7685                         }
7686                 }
7687                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7688                         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]);
7689                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7690                 {
7691                         // if this is opaque use alpha blend which will darken the earlier
7692                         // passes cheaply.
7693                         //
7694                         // if this is an alpha blended material, all the earlier passes
7695                         // were darkened by fog already, so we only need to add the fog
7696                         // color ontop through the fog mask texture
7697                         //
7698                         // if this is an additive blended material, all the earlier passes
7699                         // were darkened by fog already, and we should not add fog color
7700                         // (because the background was not darkened, there is no fog color
7701                         // that was lost behind it).
7702                         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]);
7703                 }
7704         }
7705
7706         return t->currentframe;
7707 }
7708
7709 rsurfacestate_t rsurface;
7710
7711 void RSurf_ActiveWorldEntity(void)
7712 {
7713         dp_model_t *model = r_refdef.scene.worldmodel;
7714         //if (rsurface.entity == r_refdef.scene.worldentity)
7715         //      return;
7716         rsurface.entity = r_refdef.scene.worldentity;
7717         rsurface.skeleton = NULL;
7718         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7719         rsurface.ent_skinnum = 0;
7720         rsurface.ent_qwskin = -1;
7721         rsurface.ent_shadertime = 0;
7722         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7723         rsurface.matrix = identitymatrix;
7724         rsurface.inversematrix = identitymatrix;
7725         rsurface.matrixscale = 1;
7726         rsurface.inversematrixscale = 1;
7727         R_EntityMatrix(&identitymatrix);
7728         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7729         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7730         rsurface.fograngerecip = r_refdef.fograngerecip;
7731         rsurface.fogheightfade = r_refdef.fogheightfade;
7732         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7733         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7734         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7735         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7736         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7737         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7738         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7739         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7740         rsurface.colormod[3] = 1;
7741         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);
7742         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7743         rsurface.frameblend[0].lerp = 1;
7744         rsurface.ent_alttextures = false;
7745         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7746         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7747         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7748         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7749         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7750         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7751         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7752         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7753         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7754         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7755         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7756         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7757         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7758         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7759         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7760         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7761         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7762         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7763         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7764         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7765         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7766         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7767         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7768         rsurface.modelelement3i = model->surfmesh.data_element3i;
7769         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7770         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7771         rsurface.modelelement3s = model->surfmesh.data_element3s;
7772         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7773         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7774         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7775         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7776         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7777         rsurface.modelsurfaces = model->data_surfaces;
7778         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7779         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7780         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7781         rsurface.modelgeneratedvertex = false;
7782         rsurface.batchgeneratedvertex = false;
7783         rsurface.batchfirstvertex = 0;
7784         rsurface.batchnumvertices = 0;
7785         rsurface.batchfirsttriangle = 0;
7786         rsurface.batchnumtriangles = 0;
7787         rsurface.batchvertex3f  = NULL;
7788         rsurface.batchvertex3f_vertexbuffer = NULL;
7789         rsurface.batchvertex3f_bufferoffset = 0;
7790         rsurface.batchsvector3f = NULL;
7791         rsurface.batchsvector3f_vertexbuffer = NULL;
7792         rsurface.batchsvector3f_bufferoffset = 0;
7793         rsurface.batchtvector3f = NULL;
7794         rsurface.batchtvector3f_vertexbuffer = NULL;
7795         rsurface.batchtvector3f_bufferoffset = 0;
7796         rsurface.batchnormal3f  = NULL;
7797         rsurface.batchnormal3f_vertexbuffer = NULL;
7798         rsurface.batchnormal3f_bufferoffset = 0;
7799         rsurface.batchlightmapcolor4f = NULL;
7800         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7801         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7802         rsurface.batchtexcoordtexture2f = NULL;
7803         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7804         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7805         rsurface.batchtexcoordlightmap2f = NULL;
7806         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7807         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7808         rsurface.batchvertexmesh = NULL;
7809         rsurface.batchvertexmeshbuffer = NULL;
7810         rsurface.batchvertex3fbuffer = NULL;
7811         rsurface.batchelement3i = NULL;
7812         rsurface.batchelement3i_indexbuffer = NULL;
7813         rsurface.batchelement3i_bufferoffset = 0;
7814         rsurface.batchelement3s = NULL;
7815         rsurface.batchelement3s_indexbuffer = NULL;
7816         rsurface.batchelement3s_bufferoffset = 0;
7817         rsurface.passcolor4f = NULL;
7818         rsurface.passcolor4f_vertexbuffer = NULL;
7819         rsurface.passcolor4f_bufferoffset = 0;
7820 }
7821
7822 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7823 {
7824         dp_model_t *model = ent->model;
7825         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7826         //      return;
7827         rsurface.entity = (entity_render_t *)ent;
7828         rsurface.skeleton = ent->skeleton;
7829         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7830         rsurface.ent_skinnum = ent->skinnum;
7831         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;
7832         rsurface.ent_shadertime = ent->shadertime;
7833         rsurface.ent_flags = ent->flags;
7834         rsurface.matrix = ent->matrix;
7835         rsurface.inversematrix = ent->inversematrix;
7836         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7837         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7838         R_EntityMatrix(&rsurface.matrix);
7839         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7840         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7841         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7842         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7843         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7844         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7845         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7846         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7847         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7848         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7849         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7850         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7851         rsurface.colormod[3] = ent->alpha;
7852         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7853         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7854         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7855         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7856         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7857         if (ent->model->brush.submodel && !prepass)
7858         {
7859                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7860                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7861         }
7862         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7863         {
7864                 if (ent->animcache_vertex3f)
7865                 {
7866                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7867                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7868                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7869                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7870                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7871                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7872                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7873                 }
7874                 else if (wanttangents)
7875                 {
7876                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7877                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7878                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7879                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7880                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7881                         rsurface.modelvertexmesh = NULL;
7882                         rsurface.modelvertexmeshbuffer = NULL;
7883                         rsurface.modelvertex3fbuffer = NULL;
7884                 }
7885                 else if (wantnormals)
7886                 {
7887                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7888                         rsurface.modelsvector3f = NULL;
7889                         rsurface.modeltvector3f = NULL;
7890                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7891                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7892                         rsurface.modelvertexmesh = NULL;
7893                         rsurface.modelvertexmeshbuffer = NULL;
7894                         rsurface.modelvertex3fbuffer = NULL;
7895                 }
7896                 else
7897                 {
7898                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7899                         rsurface.modelsvector3f = NULL;
7900                         rsurface.modeltvector3f = NULL;
7901                         rsurface.modelnormal3f = NULL;
7902                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7903                         rsurface.modelvertexmesh = NULL;
7904                         rsurface.modelvertexmeshbuffer = NULL;
7905                         rsurface.modelvertex3fbuffer = NULL;
7906                 }
7907                 rsurface.modelvertex3f_vertexbuffer = 0;
7908                 rsurface.modelvertex3f_bufferoffset = 0;
7909                 rsurface.modelsvector3f_vertexbuffer = 0;
7910                 rsurface.modelsvector3f_bufferoffset = 0;
7911                 rsurface.modeltvector3f_vertexbuffer = 0;
7912                 rsurface.modeltvector3f_bufferoffset = 0;
7913                 rsurface.modelnormal3f_vertexbuffer = 0;
7914                 rsurface.modelnormal3f_bufferoffset = 0;
7915                 rsurface.modelgeneratedvertex = true;
7916         }
7917         else
7918         {
7919                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7920                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7921                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7922                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7923                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7924                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7925                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7926                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7927                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7928                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7929                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7930                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7931                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7932                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7933                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7934                 rsurface.modelgeneratedvertex = false;
7935         }
7936         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7937         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7938         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7939         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7940         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7941         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7942         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7943         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7944         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7945         rsurface.modelelement3i = model->surfmesh.data_element3i;
7946         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7947         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7948         rsurface.modelelement3s = model->surfmesh.data_element3s;
7949         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7950         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7951         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7952         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7953         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7954         rsurface.modelsurfaces = model->data_surfaces;
7955         rsurface.batchgeneratedvertex = false;
7956         rsurface.batchfirstvertex = 0;
7957         rsurface.batchnumvertices = 0;
7958         rsurface.batchfirsttriangle = 0;
7959         rsurface.batchnumtriangles = 0;
7960         rsurface.batchvertex3f  = NULL;
7961         rsurface.batchvertex3f_vertexbuffer = NULL;
7962         rsurface.batchvertex3f_bufferoffset = 0;
7963         rsurface.batchsvector3f = NULL;
7964         rsurface.batchsvector3f_vertexbuffer = NULL;
7965         rsurface.batchsvector3f_bufferoffset = 0;
7966         rsurface.batchtvector3f = NULL;
7967         rsurface.batchtvector3f_vertexbuffer = NULL;
7968         rsurface.batchtvector3f_bufferoffset = 0;
7969         rsurface.batchnormal3f  = NULL;
7970         rsurface.batchnormal3f_vertexbuffer = NULL;
7971         rsurface.batchnormal3f_bufferoffset = 0;
7972         rsurface.batchlightmapcolor4f = NULL;
7973         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7974         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7975         rsurface.batchtexcoordtexture2f = NULL;
7976         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7977         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7978         rsurface.batchtexcoordlightmap2f = NULL;
7979         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7980         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7981         rsurface.batchvertexmesh = NULL;
7982         rsurface.batchvertexmeshbuffer = NULL;
7983         rsurface.batchvertex3fbuffer = NULL;
7984         rsurface.batchelement3i = NULL;
7985         rsurface.batchelement3i_indexbuffer = NULL;
7986         rsurface.batchelement3i_bufferoffset = 0;
7987         rsurface.batchelement3s = NULL;
7988         rsurface.batchelement3s_indexbuffer = NULL;
7989         rsurface.batchelement3s_bufferoffset = 0;
7990         rsurface.passcolor4f = NULL;
7991         rsurface.passcolor4f_vertexbuffer = NULL;
7992         rsurface.passcolor4f_bufferoffset = 0;
7993 }
7994
7995 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)
7996 {
7997         rsurface.entity = r_refdef.scene.worldentity;
7998         rsurface.skeleton = NULL;
7999         rsurface.ent_skinnum = 0;
8000         rsurface.ent_qwskin = -1;
8001         rsurface.ent_shadertime = shadertime;
8002         rsurface.ent_flags = entflags;
8003         rsurface.modelnumvertices = numvertices;
8004         rsurface.modelnumtriangles = numtriangles;
8005         rsurface.matrix = *matrix;
8006         rsurface.inversematrix = *inversematrix;
8007         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8008         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8009         R_EntityMatrix(&rsurface.matrix);
8010         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8011         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8012         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8013         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8014         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8015         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8016         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8017         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8018         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8019         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8020         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8021         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8022         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);
8023         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8024         rsurface.frameblend[0].lerp = 1;
8025         rsurface.ent_alttextures = false;
8026         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8027         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8028         if (wanttangents)
8029         {
8030                 rsurface.modelvertex3f = (float *)vertex3f;
8031                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8032                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8033                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8034         }
8035         else if (wantnormals)
8036         {
8037                 rsurface.modelvertex3f = (float *)vertex3f;
8038                 rsurface.modelsvector3f = NULL;
8039                 rsurface.modeltvector3f = NULL;
8040                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8041         }
8042         else
8043         {
8044                 rsurface.modelvertex3f = (float *)vertex3f;
8045                 rsurface.modelsvector3f = NULL;
8046                 rsurface.modeltvector3f = NULL;
8047                 rsurface.modelnormal3f = NULL;
8048         }
8049         rsurface.modelvertexmesh = NULL;
8050         rsurface.modelvertexmeshbuffer = NULL;
8051         rsurface.modelvertex3fbuffer = NULL;
8052         rsurface.modelvertex3f_vertexbuffer = 0;
8053         rsurface.modelvertex3f_bufferoffset = 0;
8054         rsurface.modelsvector3f_vertexbuffer = 0;
8055         rsurface.modelsvector3f_bufferoffset = 0;
8056         rsurface.modeltvector3f_vertexbuffer = 0;
8057         rsurface.modeltvector3f_bufferoffset = 0;
8058         rsurface.modelnormal3f_vertexbuffer = 0;
8059         rsurface.modelnormal3f_bufferoffset = 0;
8060         rsurface.modelgeneratedvertex = true;
8061         rsurface.modellightmapcolor4f  = (float *)color4f;
8062         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8063         rsurface.modellightmapcolor4f_bufferoffset = 0;
8064         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8065         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8066         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8067         rsurface.modeltexcoordlightmap2f  = NULL;
8068         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8069         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8070         rsurface.modelelement3i = (int *)element3i;
8071         rsurface.modelelement3i_indexbuffer = NULL;
8072         rsurface.modelelement3i_bufferoffset = 0;
8073         rsurface.modelelement3s = (unsigned short *)element3s;
8074         rsurface.modelelement3s_indexbuffer = NULL;
8075         rsurface.modelelement3s_bufferoffset = 0;
8076         rsurface.modellightmapoffsets = NULL;
8077         rsurface.modelsurfaces = NULL;
8078         rsurface.batchgeneratedvertex = false;
8079         rsurface.batchfirstvertex = 0;
8080         rsurface.batchnumvertices = 0;
8081         rsurface.batchfirsttriangle = 0;
8082         rsurface.batchnumtriangles = 0;
8083         rsurface.batchvertex3f  = NULL;
8084         rsurface.batchvertex3f_vertexbuffer = NULL;
8085         rsurface.batchvertex3f_bufferoffset = 0;
8086         rsurface.batchsvector3f = NULL;
8087         rsurface.batchsvector3f_vertexbuffer = NULL;
8088         rsurface.batchsvector3f_bufferoffset = 0;
8089         rsurface.batchtvector3f = NULL;
8090         rsurface.batchtvector3f_vertexbuffer = NULL;
8091         rsurface.batchtvector3f_bufferoffset = 0;
8092         rsurface.batchnormal3f  = NULL;
8093         rsurface.batchnormal3f_vertexbuffer = NULL;
8094         rsurface.batchnormal3f_bufferoffset = 0;
8095         rsurface.batchlightmapcolor4f = NULL;
8096         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8097         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8098         rsurface.batchtexcoordtexture2f = NULL;
8099         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8100         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8101         rsurface.batchtexcoordlightmap2f = NULL;
8102         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8103         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8104         rsurface.batchvertexmesh = NULL;
8105         rsurface.batchvertexmeshbuffer = NULL;
8106         rsurface.batchvertex3fbuffer = NULL;
8107         rsurface.batchelement3i = NULL;
8108         rsurface.batchelement3i_indexbuffer = NULL;
8109         rsurface.batchelement3i_bufferoffset = 0;
8110         rsurface.batchelement3s = NULL;
8111         rsurface.batchelement3s_indexbuffer = NULL;
8112         rsurface.batchelement3s_bufferoffset = 0;
8113         rsurface.passcolor4f = NULL;
8114         rsurface.passcolor4f_vertexbuffer = NULL;
8115         rsurface.passcolor4f_bufferoffset = 0;
8116
8117         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8118         {
8119                 if ((wantnormals || wanttangents) && !normal3f)
8120                 {
8121                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8122                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8123                 }
8124                 if (wanttangents && !svector3f)
8125                 {
8126                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8127                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8128                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8129                 }
8130         }
8131 }
8132
8133 float RSurf_FogPoint(const float *v)
8134 {
8135         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8136         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8137         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8138         float FogHeightFade = r_refdef.fogheightfade;
8139         float fogfrac;
8140         unsigned int fogmasktableindex;
8141         if (r_refdef.fogplaneviewabove)
8142                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8143         else
8144                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8145         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8146         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8147 }
8148
8149 float RSurf_FogVertex(const float *v)
8150 {
8151         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8152         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8153         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8154         float FogHeightFade = rsurface.fogheightfade;
8155         float fogfrac;
8156         unsigned int fogmasktableindex;
8157         if (r_refdef.fogplaneviewabove)
8158                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8159         else
8160                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8161         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8162         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8163 }
8164
8165 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8166 {
8167         int i;
8168         for (i = 0;i < numelements;i++)
8169                 outelement3i[i] = inelement3i[i] + adjust;
8170 }
8171
8172 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8173 extern cvar_t gl_vbo;
8174 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8175 {
8176         int deformindex;
8177         int firsttriangle;
8178         int numtriangles;
8179         int firstvertex;
8180         int endvertex;
8181         int numvertices;
8182         int surfacefirsttriangle;
8183         int surfacenumtriangles;
8184         int surfacefirstvertex;
8185         int surfaceendvertex;
8186         int surfacenumvertices;
8187         int batchnumvertices;
8188         int batchnumtriangles;
8189         int needsupdate;
8190         int i, j;
8191         qboolean gaps;
8192         qboolean dynamicvertex;
8193         float amplitude;
8194         float animpos;
8195         float scale;
8196         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8197         float waveparms[4];
8198         q3shaderinfo_deform_t *deform;
8199         const msurface_t *surface, *firstsurface;
8200         r_vertexmesh_t *vertexmesh;
8201         if (!texturenumsurfaces)
8202                 return;
8203         // find vertex range of this surface batch
8204         gaps = false;
8205         firstsurface = texturesurfacelist[0];
8206         firsttriangle = firstsurface->num_firsttriangle;
8207         batchnumvertices = 0;
8208         batchnumtriangles = 0;
8209         firstvertex = endvertex = firstsurface->num_firstvertex;
8210         for (i = 0;i < texturenumsurfaces;i++)
8211         {
8212                 surface = texturesurfacelist[i];
8213                 if (surface != firstsurface + i)
8214                         gaps = true;
8215                 surfacefirstvertex = surface->num_firstvertex;
8216                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8217                 surfacenumvertices = surface->num_vertices;
8218                 surfacenumtriangles = surface->num_triangles;
8219                 if (firstvertex > surfacefirstvertex)
8220                         firstvertex = surfacefirstvertex;
8221                 if (endvertex < surfaceendvertex)
8222                         endvertex = surfaceendvertex;
8223                 batchnumvertices += surfacenumvertices;
8224                 batchnumtriangles += surfacenumtriangles;
8225         }
8226
8227         // we now know the vertex range used, and if there are any gaps in it
8228         rsurface.batchfirstvertex = firstvertex;
8229         rsurface.batchnumvertices = endvertex - firstvertex;
8230         rsurface.batchfirsttriangle = firsttriangle;
8231         rsurface.batchnumtriangles = batchnumtriangles;
8232
8233         // this variable holds flags for which properties have been updated that
8234         // may require regenerating vertexmesh array...
8235         needsupdate = 0;
8236
8237         // check if any dynamic vertex processing must occur
8238         dynamicvertex = false;
8239
8240         // if there is a chance of animated vertex colors, it's a dynamic batch
8241         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8242         {
8243                 dynamicvertex = true;
8244                 batchneed |= BATCHNEED_NOGAPS;
8245                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8246         }
8247
8248         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8249         {
8250                 switch (deform->deform)
8251                 {
8252                 default:
8253                 case Q3DEFORM_PROJECTIONSHADOW:
8254                 case Q3DEFORM_TEXT0:
8255                 case Q3DEFORM_TEXT1:
8256                 case Q3DEFORM_TEXT2:
8257                 case Q3DEFORM_TEXT3:
8258                 case Q3DEFORM_TEXT4:
8259                 case Q3DEFORM_TEXT5:
8260                 case Q3DEFORM_TEXT6:
8261                 case Q3DEFORM_TEXT7:
8262                 case Q3DEFORM_NONE:
8263                         break;
8264                 case Q3DEFORM_AUTOSPRITE:
8265                         dynamicvertex = true;
8266                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8267                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8268                         break;
8269                 case Q3DEFORM_AUTOSPRITE2:
8270                         dynamicvertex = true;
8271                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8272                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8273                         break;
8274                 case Q3DEFORM_NORMAL:
8275                         dynamicvertex = true;
8276                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8277                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8278                         break;
8279                 case Q3DEFORM_WAVE:
8280                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8281                                 break; // if wavefunc is a nop, ignore this transform
8282                         dynamicvertex = true;
8283                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8284                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8285                         break;
8286                 case Q3DEFORM_BULGE:
8287                         dynamicvertex = true;
8288                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8289                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8290                         break;
8291                 case Q3DEFORM_MOVE:
8292                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8293                                 break; // if wavefunc is a nop, ignore this transform
8294                         dynamicvertex = true;
8295                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8296                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8297                         break;
8298                 }
8299         }
8300         switch(rsurface.texture->tcgen.tcgen)
8301         {
8302         default:
8303         case Q3TCGEN_TEXTURE:
8304                 break;
8305         case Q3TCGEN_LIGHTMAP:
8306                 dynamicvertex = true;
8307                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8308                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8309                 break;
8310         case Q3TCGEN_VECTOR:
8311                 dynamicvertex = true;
8312                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8313                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8314                 break;
8315         case Q3TCGEN_ENVIRONMENT:
8316                 dynamicvertex = true;
8317                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8318                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8319                 break;
8320         }
8321         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8322         {
8323                 dynamicvertex = true;
8324                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8325                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8326         }
8327
8328         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8329         {
8330                 dynamicvertex = true;
8331                 batchneed |= BATCHNEED_NOGAPS;
8332                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8333         }
8334
8335         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8336         {
8337                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8338                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8339                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8340                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8341                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8342                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8343                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8344         }
8345
8346         // when the model data has no vertex buffer (dynamic mesh), we need to
8347         // eliminate gaps
8348         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8349                 batchneed |= BATCHNEED_NOGAPS;
8350
8351         // if needsupdate, we have to do a dynamic vertex batch for sure
8352         if (needsupdate & batchneed)
8353                 dynamicvertex = true;
8354
8355         // see if we need to build vertexmesh from arrays
8356         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8357                 dynamicvertex = true;
8358
8359         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8360         // also some drivers strongly dislike firstvertex
8361         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8362                 dynamicvertex = true;
8363
8364         rsurface.batchvertex3f = rsurface.modelvertex3f;
8365         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8366         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8367         rsurface.batchsvector3f = rsurface.modelsvector3f;
8368         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8369         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8370         rsurface.batchtvector3f = rsurface.modeltvector3f;
8371         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8372         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8373         rsurface.batchnormal3f = rsurface.modelnormal3f;
8374         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8375         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8376         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8377         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8378         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8379         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8380         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8381         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8382         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8383         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8384         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8385         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8386         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8387         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8388         rsurface.batchelement3i = rsurface.modelelement3i;
8389         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8390         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8391         rsurface.batchelement3s = rsurface.modelelement3s;
8392         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8393         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8394
8395         // if any dynamic vertex processing has to occur in software, we copy the
8396         // entire surface list together before processing to rebase the vertices
8397         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8398         //
8399         // if any gaps exist and we do not have a static vertex buffer, we have to
8400         // copy the surface list together to avoid wasting upload bandwidth on the
8401         // vertices in the gaps.
8402         //
8403         // if gaps exist and we have a static vertex buffer, we still have to
8404         // combine the index buffer ranges into one dynamic index buffer.
8405         //
8406         // in all cases we end up with data that can be drawn in one call.
8407
8408         if (!dynamicvertex)
8409         {
8410                 // static vertex data, just set pointers...
8411                 rsurface.batchgeneratedvertex = false;
8412                 // if there are gaps, we want to build a combined index buffer,
8413                 // otherwise use the original static buffer with an appropriate offset
8414                 if (gaps)
8415                 {
8416                         // build a new triangle elements array for this batch
8417                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8418                         rsurface.batchfirsttriangle = 0;
8419                         numtriangles = 0;
8420                         for (i = 0;i < texturenumsurfaces;i++)
8421                         {
8422                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8423                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8424                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8425                                 numtriangles += surfacenumtriangles;
8426                         }
8427                         rsurface.batchelement3i_indexbuffer = NULL;
8428                         rsurface.batchelement3i_bufferoffset = 0;
8429                         rsurface.batchelement3s = NULL;
8430                         rsurface.batchelement3s_indexbuffer = NULL;
8431                         rsurface.batchelement3s_bufferoffset = 0;
8432                         if (endvertex <= 65536)
8433                         {
8434                                 // make a 16bit (unsigned short) index array if possible
8435                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8436                                 for (i = 0;i < numtriangles*3;i++)
8437                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8438                         }
8439                 }
8440                 return;
8441         }
8442
8443         // something needs software processing, do it for real...
8444         // we only directly handle separate array data in this case and then
8445         // generate interleaved data if needed...
8446         rsurface.batchgeneratedvertex = true;
8447
8448         // now copy the vertex data into a combined array and make an index array
8449         // (this is what Quake3 does all the time)
8450         //if (gaps || rsurface.batchfirstvertex)
8451         {
8452                 rsurface.batchvertex3fbuffer = NULL;
8453                 rsurface.batchvertexmesh = NULL;
8454                 rsurface.batchvertexmeshbuffer = NULL;
8455                 rsurface.batchvertex3f = NULL;
8456                 rsurface.batchvertex3f_vertexbuffer = NULL;
8457                 rsurface.batchvertex3f_bufferoffset = 0;
8458                 rsurface.batchsvector3f = NULL;
8459                 rsurface.batchsvector3f_vertexbuffer = NULL;
8460                 rsurface.batchsvector3f_bufferoffset = 0;
8461                 rsurface.batchtvector3f = NULL;
8462                 rsurface.batchtvector3f_vertexbuffer = NULL;
8463                 rsurface.batchtvector3f_bufferoffset = 0;
8464                 rsurface.batchnormal3f = NULL;
8465                 rsurface.batchnormal3f_vertexbuffer = NULL;
8466                 rsurface.batchnormal3f_bufferoffset = 0;
8467                 rsurface.batchlightmapcolor4f = NULL;
8468                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8469                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8470                 rsurface.batchtexcoordtexture2f = NULL;
8471                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8472                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8473                 rsurface.batchtexcoordlightmap2f = NULL;
8474                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8475                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8476                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8477                 rsurface.batchelement3i_indexbuffer = NULL;
8478                 rsurface.batchelement3i_bufferoffset = 0;
8479                 rsurface.batchelement3s = NULL;
8480                 rsurface.batchelement3s_indexbuffer = NULL;
8481                 rsurface.batchelement3s_bufferoffset = 0;
8482                 // we'll only be setting up certain arrays as needed
8483                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8484                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8485                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8486                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8487                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8488                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8489                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8490                 {
8491                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8492                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8493                 }
8494                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8495                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8496                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8497                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8498                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8499                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8500                 numvertices = 0;
8501                 numtriangles = 0;
8502                 for (i = 0;i < texturenumsurfaces;i++)
8503                 {
8504                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8505                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8506                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8507                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8508                         // copy only the data requested
8509                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8510                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8511                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8512                         {
8513                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8514                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8515                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8516                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8517                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8518                                 {
8519                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8520                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8521                                 }
8522                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8523                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8524                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8525                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8526                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8527                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8528                         }
8529                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8530                         numvertices += surfacenumvertices;
8531                         numtriangles += surfacenumtriangles;
8532                 }
8533
8534                 // generate a 16bit index array as well if possible
8535                 // (in general, dynamic batches fit)
8536                 if (numvertices <= 65536)
8537                 {
8538                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8539                         for (i = 0;i < numtriangles*3;i++)
8540                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8541                 }
8542
8543                 // since we've copied everything, the batch now starts at 0
8544                 rsurface.batchfirstvertex = 0;
8545                 rsurface.batchnumvertices = batchnumvertices;
8546                 rsurface.batchfirsttriangle = 0;
8547                 rsurface.batchnumtriangles = batchnumtriangles;
8548         }
8549
8550         // q1bsp surfaces rendered in vertex color mode have to have colors
8551         // calculated based on lightstyles
8552         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8553         {
8554                 // generate color arrays for the surfaces in this list
8555                 int c[4];
8556                 int scale;
8557                 int size3;
8558                 const int *offsets;
8559                 const unsigned char *lm;
8560                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8561                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8562                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8563                 numvertices = 0;
8564                 for (i = 0;i < texturenumsurfaces;i++)
8565                 {
8566                         surface = texturesurfacelist[i];
8567                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8568                         surfacenumvertices = surface->num_vertices;
8569                         if (surface->lightmapinfo->samples)
8570                         {
8571                                 for (j = 0;j < surfacenumvertices;j++)
8572                                 {
8573                                         lm = surface->lightmapinfo->samples + offsets[j];
8574                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8575                                         VectorScale(lm, scale, c);
8576                                         if (surface->lightmapinfo->styles[1] != 255)
8577                                         {
8578                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8579                                                 lm += size3;
8580                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8581                                                 VectorMA(c, scale, lm, c);
8582                                                 if (surface->lightmapinfo->styles[2] != 255)
8583                                                 {
8584                                                         lm += size3;
8585                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8586                                                         VectorMA(c, scale, lm, c);
8587                                                         if (surface->lightmapinfo->styles[3] != 255)
8588                                                         {
8589                                                                 lm += size3;
8590                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8591                                                                 VectorMA(c, scale, lm, c);
8592                                                         }
8593                                                 }
8594                                         }
8595                                         c[0] >>= 7;
8596                                         c[1] >>= 7;
8597                                         c[2] >>= 7;
8598                                         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);
8599                                         numvertices++;
8600                                 }
8601                         }
8602                         else
8603                         {
8604                                 for (j = 0;j < surfacenumvertices;j++)
8605                                 {
8606                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8607                                         numvertices++;
8608                                 }
8609                         }
8610                 }
8611         }
8612
8613         // if vertices are deformed (sprite flares and things in maps, possibly
8614         // water waves, bulges and other deformations), modify the copied vertices
8615         // in place
8616         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8617         {
8618                 switch (deform->deform)
8619                 {
8620                 default:
8621                 case Q3DEFORM_PROJECTIONSHADOW:
8622                 case Q3DEFORM_TEXT0:
8623                 case Q3DEFORM_TEXT1:
8624                 case Q3DEFORM_TEXT2:
8625                 case Q3DEFORM_TEXT3:
8626                 case Q3DEFORM_TEXT4:
8627                 case Q3DEFORM_TEXT5:
8628                 case Q3DEFORM_TEXT6:
8629                 case Q3DEFORM_TEXT7:
8630                 case Q3DEFORM_NONE:
8631                         break;
8632                 case Q3DEFORM_AUTOSPRITE:
8633                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8634                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8635                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8636                         VectorNormalize(newforward);
8637                         VectorNormalize(newright);
8638                         VectorNormalize(newup);
8639 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8640 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8641 //                      rsurface.batchvertex3f_bufferoffset = 0;
8642 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8643 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8644 //                      rsurface.batchsvector3f_bufferoffset = 0;
8645 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8646 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8647 //                      rsurface.batchtvector3f_bufferoffset = 0;
8648 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8649 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8650 //                      rsurface.batchnormal3f_bufferoffset = 0;
8651                         // a single autosprite surface can contain multiple sprites...
8652                         for (j = 0;j < batchnumvertices - 3;j += 4)
8653                         {
8654                                 VectorClear(center);
8655                                 for (i = 0;i < 4;i++)
8656                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8657                                 VectorScale(center, 0.25f, center);
8658                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8659                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8660                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8661                                 for (i = 0;i < 4;i++)
8662                                 {
8663                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8664                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8665                                 }
8666                         }
8667                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8668                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8669                         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);
8670                         break;
8671                 case Q3DEFORM_AUTOSPRITE2:
8672                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8673                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8674                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8675                         VectorNormalize(newforward);
8676                         VectorNormalize(newright);
8677                         VectorNormalize(newup);
8678 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8679 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8680 //                      rsurface.batchvertex3f_bufferoffset = 0;
8681                         {
8682                                 const float *v1, *v2;
8683                                 vec3_t start, end;
8684                                 float f, l;
8685                                 struct
8686                                 {
8687                                         float length2;
8688                                         const float *v1;
8689                                         const float *v2;
8690                                 }
8691                                 shortest[2];
8692                                 memset(shortest, 0, sizeof(shortest));
8693                                 // a single autosprite surface can contain multiple sprites...
8694                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8695                                 {
8696                                         VectorClear(center);
8697                                         for (i = 0;i < 4;i++)
8698                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8699                                         VectorScale(center, 0.25f, center);
8700                                         // find the two shortest edges, then use them to define the
8701                                         // axis vectors for rotating around the central axis
8702                                         for (i = 0;i < 6;i++)
8703                                         {
8704                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8705                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8706                                                 l = VectorDistance2(v1, v2);
8707                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8708                                                 if (v1[2] != v2[2])
8709                                                         l += (1.0f / 1024.0f);
8710                                                 if (shortest[0].length2 > l || i == 0)
8711                                                 {
8712                                                         shortest[1] = shortest[0];
8713                                                         shortest[0].length2 = l;
8714                                                         shortest[0].v1 = v1;
8715                                                         shortest[0].v2 = v2;
8716                                                 }
8717                                                 else if (shortest[1].length2 > l || i == 1)
8718                                                 {
8719                                                         shortest[1].length2 = l;
8720                                                         shortest[1].v1 = v1;
8721                                                         shortest[1].v2 = v2;
8722                                                 }
8723                                         }
8724                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8725                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8726                                         // this calculates the right vector from the shortest edge
8727                                         // and the up vector from the edge midpoints
8728                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8729                                         VectorNormalize(right);
8730                                         VectorSubtract(end, start, up);
8731                                         VectorNormalize(up);
8732                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8733                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8734                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8735                                         VectorNegate(forward, forward);
8736                                         VectorReflect(forward, 0, up, forward);
8737                                         VectorNormalize(forward);
8738                                         CrossProduct(up, forward, newright);
8739                                         VectorNormalize(newright);
8740                                         // rotate the quad around the up axis vector, this is made
8741                                         // especially easy by the fact we know the quad is flat,
8742                                         // so we only have to subtract the center position and
8743                                         // measure distance along the right vector, and then
8744                                         // multiply that by the newright vector and add back the
8745                                         // center position
8746                                         // we also need to subtract the old position to undo the
8747                                         // displacement from the center, which we do with a
8748                                         // DotProduct, the subtraction/addition of center is also
8749                                         // optimized into DotProducts here
8750                                         l = DotProduct(right, center);
8751                                         for (i = 0;i < 4;i++)
8752                                         {
8753                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8754                                                 f = DotProduct(right, v1) - l;
8755                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8756                                         }
8757                                 }
8758                         }
8759                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8760                         {
8761 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8762 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8763 //                              rsurface.batchnormal3f_bufferoffset = 0;
8764                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8765                         }
8766                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8767                         {
8768 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8769 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8770 //                              rsurface.batchsvector3f_bufferoffset = 0;
8771 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8772 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8773 //                              rsurface.batchtvector3f_bufferoffset = 0;
8774                                 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);
8775                         }
8776                         break;
8777                 case Q3DEFORM_NORMAL:
8778                         // deform the normals to make reflections wavey
8779                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8780                         rsurface.batchnormal3f_vertexbuffer = NULL;
8781                         rsurface.batchnormal3f_bufferoffset = 0;
8782                         for (j = 0;j < batchnumvertices;j++)
8783                         {
8784                                 float vertex[3];
8785                                 float *normal = rsurface.batchnormal3f + 3*j;
8786                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8787                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8788                                 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]);
8789                                 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]);
8790                                 VectorNormalize(normal);
8791                         }
8792                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8793                         {
8794 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8795 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8796 //                              rsurface.batchsvector3f_bufferoffset = 0;
8797 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8798 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8799 //                              rsurface.batchtvector3f_bufferoffset = 0;
8800                                 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);
8801                         }
8802                         break;
8803                 case Q3DEFORM_WAVE:
8804                         // deform vertex array to make wavey water and flags and such
8805                         waveparms[0] = deform->waveparms[0];
8806                         waveparms[1] = deform->waveparms[1];
8807                         waveparms[2] = deform->waveparms[2];
8808                         waveparms[3] = deform->waveparms[3];
8809                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8810                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8811                         // this is how a divisor of vertex influence on deformation
8812                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8813                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8814 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8815 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8816 //                      rsurface.batchvertex3f_bufferoffset = 0;
8817 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8818 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8819 //                      rsurface.batchnormal3f_bufferoffset = 0;
8820                         for (j = 0;j < batchnumvertices;j++)
8821                         {
8822                                 // if the wavefunc depends on time, evaluate it per-vertex
8823                                 if (waveparms[3])
8824                                 {
8825                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8826                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8827                                 }
8828                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8829                         }
8830                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8831                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8832                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8833                         {
8834 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8835 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8836 //                              rsurface.batchsvector3f_bufferoffset = 0;
8837 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8838 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8839 //                              rsurface.batchtvector3f_bufferoffset = 0;
8840                                 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);
8841                         }
8842                         break;
8843                 case Q3DEFORM_BULGE:
8844                         // deform vertex array to make the surface have moving bulges
8845 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8846 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8847 //                      rsurface.batchvertex3f_bufferoffset = 0;
8848 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8849 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8850 //                      rsurface.batchnormal3f_bufferoffset = 0;
8851                         for (j = 0;j < batchnumvertices;j++)
8852                         {
8853                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8854                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8855                         }
8856                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8857                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8858                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8859                         {
8860 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8861 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8862 //                              rsurface.batchsvector3f_bufferoffset = 0;
8863 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8864 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8865 //                              rsurface.batchtvector3f_bufferoffset = 0;
8866                                 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);
8867                         }
8868                         break;
8869                 case Q3DEFORM_MOVE:
8870                         // deform vertex array
8871                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8872                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8873                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8874                         VectorScale(deform->parms, scale, waveparms);
8875 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8876 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8877 //                      rsurface.batchvertex3f_bufferoffset = 0;
8878                         for (j = 0;j < batchnumvertices;j++)
8879                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8880                         break;
8881                 }
8882         }
8883
8884         // generate texcoords based on the chosen texcoord source
8885         switch(rsurface.texture->tcgen.tcgen)
8886         {
8887         default:
8888         case Q3TCGEN_TEXTURE:
8889                 break;
8890         case Q3TCGEN_LIGHTMAP:
8891 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8892 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8893 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8894                 if (rsurface.batchtexcoordlightmap2f)
8895                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8896                 break;
8897         case Q3TCGEN_VECTOR:
8898 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8899 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8900 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8901                 for (j = 0;j < batchnumvertices;j++)
8902                 {
8903                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8904                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8905                 }
8906                 break;
8907         case Q3TCGEN_ENVIRONMENT:
8908                 // make environment reflections using a spheremap
8909                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8910                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8911                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8912                 for (j = 0;j < batchnumvertices;j++)
8913                 {
8914                         // identical to Q3A's method, but executed in worldspace so
8915                         // carried models can be shiny too
8916
8917                         float viewer[3], d, reflected[3], worldreflected[3];
8918
8919                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8920                         // VectorNormalize(viewer);
8921
8922                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8923
8924                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8925                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8926                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8927                         // note: this is proportinal to viewer, so we can normalize later
8928
8929                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8930                         VectorNormalize(worldreflected);
8931
8932                         // note: this sphere map only uses world x and z!
8933                         // so positive and negative y will LOOK THE SAME.
8934                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8935                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8936                 }
8937                 break;
8938         }
8939         // the only tcmod that needs software vertex processing is turbulent, so
8940         // check for it here and apply the changes if needed
8941         // and we only support that as the first one
8942         // (handling a mixture of turbulent and other tcmods would be problematic
8943         //  without punting it entirely to a software path)
8944         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8945         {
8946                 amplitude = rsurface.texture->tcmods[0].parms[1];
8947                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8948 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8949 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8950 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8951                 for (j = 0;j < batchnumvertices;j++)
8952                 {
8953                         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);
8954                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8955                 }
8956         }
8957
8958         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8959         {
8960                 // convert the modified arrays to vertex structs
8961 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8962 //              rsurface.batchvertexmeshbuffer = NULL;
8963                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8964                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8965                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8966                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8967                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8968                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8969                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8970                 {
8971                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8972                         {
8973                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8974                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8975                         }
8976                 }
8977                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8978                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8979                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8980                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8981                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8982                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8983                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8984                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8985                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8986         }
8987 }
8988
8989 void RSurf_DrawBatch(void)
8990 {
8991         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8992         // through the pipeline, killing it earlier in the pipeline would have
8993         // per-surface overhead rather than per-batch overhead, so it's best to
8994         // reject it here, before it hits glDraw.
8995         if (rsurface.batchnumtriangles == 0)
8996                 return;
8997 #if 0
8998         // batch debugging code
8999         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9000         {
9001                 int i;
9002                 int j;
9003                 int c;
9004                 const int *e;
9005                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9006                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9007                 {
9008                         c = e[i];
9009                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9010                         {
9011                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9012                                 {
9013                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9014                                                 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);
9015                                         break;
9016                                 }
9017                         }
9018                 }
9019         }
9020 #endif
9021         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);
9022 }
9023
9024 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9025 {
9026         // pick the closest matching water plane
9027         int planeindex, vertexindex, bestplaneindex = -1;
9028         float d, bestd;
9029         vec3_t vert;
9030         const float *v;
9031         r_waterstate_waterplane_t *p;
9032         qboolean prepared = false;
9033         bestd = 0;
9034         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9035         {
9036                 if(p->camera_entity != rsurface.texture->camera_entity)
9037                         continue;
9038                 d = 0;
9039                 if(!prepared)
9040                 {
9041                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9042                         prepared = true;
9043                         if(rsurface.batchnumvertices == 0)
9044                                 break;
9045                 }
9046                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9047                 {
9048                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9049                         d += fabs(PlaneDiff(vert, &p->plane));
9050                 }
9051                 if (bestd > d || bestplaneindex < 0)
9052                 {
9053                         bestd = d;
9054                         bestplaneindex = planeindex;
9055                 }
9056         }
9057         return bestplaneindex;
9058         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9059         // this situation though, as it might be better to render single larger
9060         // batches with useless stuff (backface culled for example) than to
9061         // render multiple smaller batches
9062 }
9063
9064 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9065 {
9066         int i;
9067         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9068         rsurface.passcolor4f_vertexbuffer = 0;
9069         rsurface.passcolor4f_bufferoffset = 0;
9070         for (i = 0;i < rsurface.batchnumvertices;i++)
9071                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9072 }
9073
9074 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9075 {
9076         int i;
9077         float f;
9078         const float *v;
9079         const float *c;
9080         float *c2;
9081         if (rsurface.passcolor4f)
9082         {
9083                 // generate color arrays
9084                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9085                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9086                 rsurface.passcolor4f_vertexbuffer = 0;
9087                 rsurface.passcolor4f_bufferoffset = 0;
9088                 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)
9089                 {
9090                         f = RSurf_FogVertex(v);
9091                         c2[0] = c[0] * f;
9092                         c2[1] = c[1] * f;
9093                         c2[2] = c[2] * f;
9094                         c2[3] = c[3];
9095                 }
9096         }
9097         else
9098         {
9099                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9100                 rsurface.passcolor4f_vertexbuffer = 0;
9101                 rsurface.passcolor4f_bufferoffset = 0;
9102                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9103                 {
9104                         f = RSurf_FogVertex(v);
9105                         c2[0] = f;
9106                         c2[1] = f;
9107                         c2[2] = f;
9108                         c2[3] = 1;
9109                 }
9110         }
9111 }
9112
9113 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9114 {
9115         int i;
9116         float f;
9117         const float *v;
9118         const float *c;
9119         float *c2;
9120         if (!rsurface.passcolor4f)
9121                 return;
9122         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9123         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9124         rsurface.passcolor4f_vertexbuffer = 0;
9125         rsurface.passcolor4f_bufferoffset = 0;
9126         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)
9127         {
9128                 f = RSurf_FogVertex(v);
9129                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9130                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9131                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9132                 c2[3] = c[3];
9133         }
9134 }
9135
9136 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9137 {
9138         int i;
9139         const float *c;
9140         float *c2;
9141         if (!rsurface.passcolor4f)
9142                 return;
9143         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9144         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9145         rsurface.passcolor4f_vertexbuffer = 0;
9146         rsurface.passcolor4f_bufferoffset = 0;
9147         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9148         {
9149                 c2[0] = c[0] * r;
9150                 c2[1] = c[1] * g;
9151                 c2[2] = c[2] * b;
9152                 c2[3] = c[3] * a;
9153         }
9154 }
9155
9156 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9157 {
9158         int i;
9159         const float *c;
9160         float *c2;
9161         if (!rsurface.passcolor4f)
9162                 return;
9163         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9164         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9165         rsurface.passcolor4f_vertexbuffer = 0;
9166         rsurface.passcolor4f_bufferoffset = 0;
9167         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9168         {
9169                 c2[0] = c[0] + r_refdef.scene.ambient;
9170                 c2[1] = c[1] + r_refdef.scene.ambient;
9171                 c2[2] = c[2] + r_refdef.scene.ambient;
9172                 c2[3] = c[3];
9173         }
9174 }
9175
9176 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9177 {
9178         // TODO: optimize
9179         rsurface.passcolor4f = NULL;
9180         rsurface.passcolor4f_vertexbuffer = 0;
9181         rsurface.passcolor4f_bufferoffset = 0;
9182         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9183         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9184         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9185         GL_Color(r, g, b, a);
9186         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9187         RSurf_DrawBatch();
9188 }
9189
9190 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9191 {
9192         // TODO: optimize applyfog && applycolor case
9193         // just apply fog if necessary, and tint the fog color array if necessary
9194         rsurface.passcolor4f = NULL;
9195         rsurface.passcolor4f_vertexbuffer = 0;
9196         rsurface.passcolor4f_bufferoffset = 0;
9197         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9198         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9199         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9200         GL_Color(r, g, b, a);
9201         RSurf_DrawBatch();
9202 }
9203
9204 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9205 {
9206         // TODO: optimize
9207         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9208         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9209         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9210         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9211         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9212         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9213         GL_Color(r, g, b, a);
9214         RSurf_DrawBatch();
9215 }
9216
9217 static void RSurf_DrawBatch_GL11_ClampColor(void)
9218 {
9219         int i;
9220         const float *c1;
9221         float *c2;
9222         if (!rsurface.passcolor4f)
9223                 return;
9224         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9225         {
9226                 c2[0] = bound(0.0f, c1[0], 1.0f);
9227                 c2[1] = bound(0.0f, c1[1], 1.0f);
9228                 c2[2] = bound(0.0f, c1[2], 1.0f);
9229                 c2[3] = bound(0.0f, c1[3], 1.0f);
9230         }
9231 }
9232
9233 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9234 {
9235         int i;
9236         float f;
9237         const float *v;
9238         const float *n;
9239         float *c;
9240         //vec3_t eyedir;
9241
9242         // fake shading
9243         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9244         rsurface.passcolor4f_vertexbuffer = 0;
9245         rsurface.passcolor4f_bufferoffset = 0;
9246         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)
9247         {
9248                 f = -DotProduct(r_refdef.view.forward, n);
9249                 f = max(0, f);
9250                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9251                 f *= r_refdef.lightmapintensity;
9252                 Vector4Set(c, f, f, f, 1);
9253         }
9254 }
9255
9256 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9257 {
9258         RSurf_DrawBatch_GL11_ApplyFakeLight();
9259         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9260         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9261         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9262         GL_Color(r, g, b, a);
9263         RSurf_DrawBatch();
9264 }
9265
9266 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9267 {
9268         int i;
9269         float f;
9270         float alpha;
9271         const float *v;
9272         const float *n;
9273         float *c;
9274         vec3_t ambientcolor;
9275         vec3_t diffusecolor;
9276         vec3_t lightdir;
9277         // TODO: optimize
9278         // model lighting
9279         VectorCopy(rsurface.modellight_lightdir, lightdir);
9280         f = 0.5f * r_refdef.lightmapintensity;
9281         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9282         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9283         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9284         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9285         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9286         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9287         alpha = *a;
9288         if (VectorLength2(diffusecolor) > 0)
9289         {
9290                 // q3-style directional shading
9291                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9292                 rsurface.passcolor4f_vertexbuffer = 0;
9293                 rsurface.passcolor4f_bufferoffset = 0;
9294                 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)
9295                 {
9296                         if ((f = DotProduct(n, lightdir)) > 0)
9297                                 VectorMA(ambientcolor, f, diffusecolor, c);
9298                         else
9299                                 VectorCopy(ambientcolor, c);
9300                         c[3] = alpha;
9301                 }
9302                 *r = 1;
9303                 *g = 1;
9304                 *b = 1;
9305                 *a = 1;
9306                 *applycolor = false;
9307         }
9308         else
9309         {
9310                 *r = ambientcolor[0];
9311                 *g = ambientcolor[1];
9312                 *b = ambientcolor[2];
9313                 rsurface.passcolor4f = NULL;
9314                 rsurface.passcolor4f_vertexbuffer = 0;
9315                 rsurface.passcolor4f_bufferoffset = 0;
9316         }
9317 }
9318
9319 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9320 {
9321         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9322         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9323         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9324         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9325         GL_Color(r, g, b, a);
9326         RSurf_DrawBatch();
9327 }
9328
9329 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9330 {
9331         int i;
9332         float f;
9333         const float *v;
9334         float *c;
9335
9336         // fake shading
9337         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9338         rsurface.passcolor4f_vertexbuffer = 0;
9339         rsurface.passcolor4f_bufferoffset = 0;
9340
9341         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9342         {
9343                 f = 1 - RSurf_FogVertex(v);
9344                 c[0] = r;
9345                 c[1] = g;
9346                 c[2] = b;
9347                 c[3] = f * a;
9348         }
9349 }
9350
9351 void RSurf_SetupDepthAndCulling(void)
9352 {
9353         // submodels are biased to avoid z-fighting with world surfaces that they
9354         // may be exactly overlapping (avoids z-fighting artifacts on certain
9355         // doors and things in Quake maps)
9356         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9357         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9358         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9359         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9360 }
9361
9362 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9363 {
9364         // transparent sky would be ridiculous
9365         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9366                 return;
9367         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9368         skyrenderlater = true;
9369         RSurf_SetupDepthAndCulling();
9370         GL_DepthMask(true);
9371         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9372         // skymasking on them, and Quake3 never did sky masking (unlike
9373         // software Quake and software Quake2), so disable the sky masking
9374         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9375         // and skymasking also looks very bad when noclipping outside the
9376         // level, so don't use it then either.
9377         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9378         {
9379                 R_Mesh_ResetTextureState();
9380                 if (skyrendermasked)
9381                 {
9382                         R_SetupShader_DepthOrShadow();
9383                         // depth-only (masking)
9384                         GL_ColorMask(0,0,0,0);
9385                         // just to make sure that braindead drivers don't draw
9386                         // anything despite that colormask...
9387                         GL_BlendFunc(GL_ZERO, GL_ONE);
9388                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9389                         if (rsurface.batchvertex3fbuffer)
9390                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9391                         else
9392                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9393                 }
9394                 else
9395                 {
9396                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9397                         // fog sky
9398                         GL_BlendFunc(GL_ONE, GL_ZERO);
9399                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9400                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9401                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9402                 }
9403                 RSurf_DrawBatch();
9404                 if (skyrendermasked)
9405                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9406         }
9407         R_Mesh_ResetTextureState();
9408         GL_Color(1, 1, 1, 1);
9409 }
9410
9411 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9412 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9413 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9414 {
9415         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9416                 return;
9417         if (prepass)
9418         {
9419                 // render screenspace normalmap to texture
9420                 GL_DepthMask(true);
9421                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9422                 RSurf_DrawBatch();
9423                 return;
9424         }
9425
9426         // bind lightmap texture
9427
9428         // water/refraction/reflection/camera surfaces have to be handled specially
9429         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9430         {
9431                 int start, end, startplaneindex;
9432                 for (start = 0;start < texturenumsurfaces;start = end)
9433                 {
9434                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9435                         if(startplaneindex < 0)
9436                         {
9437                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9438                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9439                                 end = start + 1;
9440                                 continue;
9441                         }
9442                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9443                                 ;
9444                         // now that we have a batch using the same planeindex, render it
9445                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9446                         {
9447                                 // render water or distortion background
9448                                 GL_DepthMask(true);
9449                                 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));
9450                                 RSurf_DrawBatch();
9451                                 // blend surface on top
9452                                 GL_DepthMask(false);
9453                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9454                                 RSurf_DrawBatch();
9455                         }
9456                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9457                         {
9458                                 // render surface with reflection texture as input
9459                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9460                                 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));
9461                                 RSurf_DrawBatch();
9462                         }
9463                 }
9464                 return;
9465         }
9466
9467         // render surface batch normally
9468         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9469         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9470         RSurf_DrawBatch();
9471 }
9472
9473 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9474 {
9475         // OpenGL 1.3 path - anything not completely ancient
9476         qboolean applycolor;
9477         qboolean applyfog;
9478         int layerindex;
9479         const texturelayer_t *layer;
9480         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);
9481         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9482
9483         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9484         {
9485                 vec4_t layercolor;
9486                 int layertexrgbscale;
9487                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9488                 {
9489                         if (layerindex == 0)
9490                                 GL_AlphaTest(true);
9491                         else
9492                         {
9493                                 GL_AlphaTest(false);
9494                                 GL_DepthFunc(GL_EQUAL);
9495                         }
9496                 }
9497                 GL_DepthMask(layer->depthmask && writedepth);
9498                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9499                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9500                 {
9501                         layertexrgbscale = 4;
9502                         VectorScale(layer->color, 0.25f, layercolor);
9503                 }
9504                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9505                 {
9506                         layertexrgbscale = 2;
9507                         VectorScale(layer->color, 0.5f, layercolor);
9508                 }
9509                 else
9510                 {
9511                         layertexrgbscale = 1;
9512                         VectorScale(layer->color, 1.0f, layercolor);
9513                 }
9514                 layercolor[3] = layer->color[3];
9515                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9516                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9517                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9518                 switch (layer->type)
9519                 {
9520                 case TEXTURELAYERTYPE_LITTEXTURE:
9521                         // single-pass lightmapped texture with 2x rgbscale
9522                         R_Mesh_TexBind(0, r_texture_white);
9523                         R_Mesh_TexMatrix(0, NULL);
9524                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9525                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9526                         R_Mesh_TexBind(1, layer->texture);
9527                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9528                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9529                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9530                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9531                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9532                         else if (FAKELIGHT_ENABLED)
9533                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9534                         else if (rsurface.uselightmaptexture)
9535                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9536                         else
9537                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9538                         break;
9539                 case TEXTURELAYERTYPE_TEXTURE:
9540                         // singletexture unlit texture with transparency support
9541                         R_Mesh_TexBind(0, layer->texture);
9542                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9543                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9544                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9545                         R_Mesh_TexBind(1, 0);
9546                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9547                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9548                         break;
9549                 case TEXTURELAYERTYPE_FOG:
9550                         // singletexture fogging
9551                         if (layer->texture)
9552                         {
9553                                 R_Mesh_TexBind(0, layer->texture);
9554                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9555                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9556                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9557                         }
9558                         else
9559                         {
9560                                 R_Mesh_TexBind(0, 0);
9561                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9562                         }
9563                         R_Mesh_TexBind(1, 0);
9564                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9565                         // generate a color array for the fog pass
9566                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9567                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9568                         RSurf_DrawBatch();
9569                         break;
9570                 default:
9571                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9572                 }
9573         }
9574         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9575         {
9576                 GL_DepthFunc(GL_LEQUAL);
9577                 GL_AlphaTest(false);
9578         }
9579 }
9580
9581 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9582 {
9583         // OpenGL 1.1 - crusty old voodoo path
9584         qboolean applyfog;
9585         int layerindex;
9586         const texturelayer_t *layer;
9587         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);
9588         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9589
9590         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9591         {
9592                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9593                 {
9594                         if (layerindex == 0)
9595                                 GL_AlphaTest(true);
9596                         else
9597                         {
9598                                 GL_AlphaTest(false);
9599                                 GL_DepthFunc(GL_EQUAL);
9600                         }
9601                 }
9602                 GL_DepthMask(layer->depthmask && writedepth);
9603                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9604                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9605                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9606                 switch (layer->type)
9607                 {
9608                 case TEXTURELAYERTYPE_LITTEXTURE:
9609                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9610                         {
9611                                 // two-pass lit texture with 2x rgbscale
9612                                 // first the lightmap pass
9613                                 R_Mesh_TexBind(0, r_texture_white);
9614                                 R_Mesh_TexMatrix(0, NULL);
9615                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9616                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9617                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9618                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9619                                 else if (FAKELIGHT_ENABLED)
9620                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9621                                 else if (rsurface.uselightmaptexture)
9622                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9623                                 else
9624                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9625                                 // then apply the texture to it
9626                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9627                                 R_Mesh_TexBind(0, layer->texture);
9628                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9629                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9630                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9631                                 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);
9632                         }
9633                         else
9634                         {
9635                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9636                                 R_Mesh_TexBind(0, layer->texture);
9637                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9638                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9639                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9640                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9641                                         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);
9642                                 else
9643                                         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);
9644                         }
9645                         break;
9646                 case TEXTURELAYERTYPE_TEXTURE:
9647                         // singletexture unlit texture with transparency support
9648                         R_Mesh_TexBind(0, layer->texture);
9649                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9650                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9651                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9652                         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);
9653                         break;
9654                 case TEXTURELAYERTYPE_FOG:
9655                         // singletexture fogging
9656                         if (layer->texture)
9657                         {
9658                                 R_Mesh_TexBind(0, layer->texture);
9659                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9660                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9661                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9662                         }
9663                         else
9664                         {
9665                                 R_Mesh_TexBind(0, 0);
9666                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9667                         }
9668                         // generate a color array for the fog pass
9669                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9670                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9671                         RSurf_DrawBatch();
9672                         break;
9673                 default:
9674                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9675                 }
9676         }
9677         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9678         {
9679                 GL_DepthFunc(GL_LEQUAL);
9680                 GL_AlphaTest(false);
9681         }
9682 }
9683
9684 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9685 {
9686         int vi;
9687         int j;
9688         r_vertexgeneric_t *batchvertex;
9689         float c[4];
9690
9691 //      R_Mesh_ResetTextureState();
9692         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9693
9694         if(rsurface.texture && rsurface.texture->currentskinframe)
9695         {
9696                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9697                 c[3] *= rsurface.texture->currentalpha;
9698         }
9699         else
9700         {
9701                 c[0] = 1;
9702                 c[1] = 0;
9703                 c[2] = 1;
9704                 c[3] = 1;
9705         }
9706
9707         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9708         {
9709                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9710                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9711                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9712         }
9713
9714         // brighten it up (as texture value 127 means "unlit")
9715         c[0] *= 2 * r_refdef.view.colorscale;
9716         c[1] *= 2 * r_refdef.view.colorscale;
9717         c[2] *= 2 * r_refdef.view.colorscale;
9718
9719         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9720                 c[3] *= r_wateralpha.value;
9721
9722         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9723         {
9724                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9725                 GL_DepthMask(false);
9726         }
9727         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9728         {
9729                 GL_BlendFunc(GL_ONE, GL_ONE);
9730                 GL_DepthMask(false);
9731         }
9732         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9733         {
9734                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9735                 GL_DepthMask(false);
9736         }
9737         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9738         {
9739                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9740                 GL_DepthMask(false);
9741         }
9742         else
9743         {
9744                 GL_BlendFunc(GL_ONE, GL_ZERO);
9745                 GL_DepthMask(writedepth);
9746         }
9747
9748         if (r_showsurfaces.integer == 3)
9749         {
9750                 rsurface.passcolor4f = NULL;
9751
9752                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9753                 {
9754                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9755
9756                         rsurface.passcolor4f = NULL;
9757                         rsurface.passcolor4f_vertexbuffer = 0;
9758                         rsurface.passcolor4f_bufferoffset = 0;
9759                 }
9760                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9761                 {
9762                         qboolean applycolor = true;
9763                         float one = 1.0;
9764
9765                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9766
9767                         r_refdef.lightmapintensity = 1;
9768                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9769                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9770                 }
9771                 else if (FAKELIGHT_ENABLED)
9772                 {
9773                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9774
9775                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9776                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9777                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9778                 }
9779                 else
9780                 {
9781                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9782
9783                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9784                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9785                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9786                 }
9787
9788                 if(!rsurface.passcolor4f)
9789                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9790
9791                 RSurf_DrawBatch_GL11_ApplyAmbient();
9792                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9793                 if(r_refdef.fogenabled)
9794                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9795                 RSurf_DrawBatch_GL11_ClampColor();
9796
9797                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9798                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9799                 RSurf_DrawBatch();
9800         }
9801         else if (!r_refdef.view.showdebug)
9802         {
9803                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9804                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9805                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9806                 {
9807                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9808                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9809                 }
9810                 R_Mesh_PrepareVertices_Generic_Unlock();
9811                 RSurf_DrawBatch();
9812         }
9813         else if (r_showsurfaces.integer == 4)
9814         {
9815                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9816                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9817                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9818                 {
9819                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9820                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9821                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9822                 }
9823                 R_Mesh_PrepareVertices_Generic_Unlock();
9824                 RSurf_DrawBatch();
9825         }
9826         else if (r_showsurfaces.integer == 2)
9827         {
9828                 const int *e;
9829                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9830                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9831                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9832                 {
9833                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9834                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9835                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9836                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9837                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9838                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9839                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9840                 }
9841                 R_Mesh_PrepareVertices_Generic_Unlock();
9842                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9843         }
9844         else
9845         {
9846                 int texturesurfaceindex;
9847                 int k;
9848                 const msurface_t *surface;
9849                 float surfacecolor4f[4];
9850                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9851                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9852                 vi = 0;
9853                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9854                 {
9855                         surface = texturesurfacelist[texturesurfaceindex];
9856                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9857                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9858                         for (j = 0;j < surface->num_vertices;j++)
9859                         {
9860                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9861                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9862                                 vi++;
9863                         }
9864                 }
9865                 R_Mesh_PrepareVertices_Generic_Unlock();
9866                 RSurf_DrawBatch();
9867         }
9868 }
9869
9870 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9871 {
9872         CHECKGLERROR
9873         RSurf_SetupDepthAndCulling();
9874         if (r_showsurfaces.integer)
9875         {
9876                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9877                 return;
9878         }
9879         switch (vid.renderpath)
9880         {
9881         case RENDERPATH_GL20:
9882         case RENDERPATH_D3D9:
9883         case RENDERPATH_D3D10:
9884         case RENDERPATH_D3D11:
9885         case RENDERPATH_SOFT:
9886         case RENDERPATH_GLES2:
9887                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9888                 break;
9889         case RENDERPATH_GL13:
9890                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9891                 break;
9892         case RENDERPATH_GL11:
9893                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9894                 break;
9895         }
9896         CHECKGLERROR
9897 }
9898
9899 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9900 {
9901         CHECKGLERROR
9902         RSurf_SetupDepthAndCulling();
9903         if (r_showsurfaces.integer)
9904         {
9905                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9906                 return;
9907         }
9908         switch (vid.renderpath)
9909         {
9910         case RENDERPATH_GL20:
9911         case RENDERPATH_D3D9:
9912         case RENDERPATH_D3D10:
9913         case RENDERPATH_D3D11:
9914         case RENDERPATH_SOFT:
9915         case RENDERPATH_GLES2:
9916                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9917                 break;
9918         case RENDERPATH_GL13:
9919                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9920                 break;
9921         case RENDERPATH_GL11:
9922                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9923                 break;
9924         }
9925         CHECKGLERROR
9926 }
9927
9928 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9929 {
9930         int i, j;
9931         int texturenumsurfaces, endsurface;
9932         texture_t *texture;
9933         const msurface_t *surface;
9934 #define MAXBATCH_TRANSPARENTSURFACES 256
9935         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9936
9937         // if the model is static it doesn't matter what value we give for
9938         // wantnormals and wanttangents, so this logic uses only rules applicable
9939         // to a model, knowing that they are meaningless otherwise
9940         if (ent == r_refdef.scene.worldentity)
9941                 RSurf_ActiveWorldEntity();
9942         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9943                 RSurf_ActiveModelEntity(ent, false, false, false);
9944         else
9945         {
9946                 switch (vid.renderpath)
9947                 {
9948                 case RENDERPATH_GL20:
9949                 case RENDERPATH_D3D9:
9950                 case RENDERPATH_D3D10:
9951                 case RENDERPATH_D3D11:
9952                 case RENDERPATH_SOFT:
9953                 case RENDERPATH_GLES2:
9954                         RSurf_ActiveModelEntity(ent, true, true, false);
9955                         break;
9956                 case RENDERPATH_GL13:
9957                 case RENDERPATH_GL11:
9958                         RSurf_ActiveModelEntity(ent, true, false, false);
9959                         break;
9960                 }
9961         }
9962
9963         if (r_transparentdepthmasking.integer)
9964         {
9965                 qboolean setup = false;
9966                 for (i = 0;i < numsurfaces;i = j)
9967                 {
9968                         j = i + 1;
9969                         surface = rsurface.modelsurfaces + surfacelist[i];
9970                         texture = surface->texture;
9971                         rsurface.texture = R_GetCurrentTexture(texture);
9972                         rsurface.lightmaptexture = NULL;
9973                         rsurface.deluxemaptexture = NULL;
9974                         rsurface.uselightmaptexture = false;
9975                         // scan ahead until we find a different texture
9976                         endsurface = min(i + 1024, numsurfaces);
9977                         texturenumsurfaces = 0;
9978                         texturesurfacelist[texturenumsurfaces++] = surface;
9979                         for (;j < endsurface;j++)
9980                         {
9981                                 surface = rsurface.modelsurfaces + surfacelist[j];
9982                                 if (texture != surface->texture)
9983                                         break;
9984                                 texturesurfacelist[texturenumsurfaces++] = surface;
9985                         }
9986                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9987                                 continue;
9988                         // render the range of surfaces as depth
9989                         if (!setup)
9990                         {
9991                                 setup = true;
9992                                 GL_ColorMask(0,0,0,0);
9993                                 GL_Color(1,1,1,1);
9994                                 GL_DepthTest(true);
9995                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9996                                 GL_DepthMask(true);
9997 //                              R_Mesh_ResetTextureState();
9998                                 R_SetupShader_DepthOrShadow();
9999                         }
10000                         RSurf_SetupDepthAndCulling();
10001                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10002                         if (rsurface.batchvertex3fbuffer)
10003                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10004                         else
10005                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10006                         RSurf_DrawBatch();
10007                 }
10008                 if (setup)
10009                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10010         }
10011
10012         for (i = 0;i < numsurfaces;i = j)
10013         {
10014                 j = i + 1;
10015                 surface = rsurface.modelsurfaces + surfacelist[i];
10016                 texture = surface->texture;
10017                 rsurface.texture = R_GetCurrentTexture(texture);
10018                 // scan ahead until we find a different texture
10019                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10020                 texturenumsurfaces = 0;
10021                 texturesurfacelist[texturenumsurfaces++] = surface;
10022                 if(FAKELIGHT_ENABLED)
10023                 {
10024                         rsurface.lightmaptexture = NULL;
10025                         rsurface.deluxemaptexture = NULL;
10026                         rsurface.uselightmaptexture = false;
10027                         for (;j < endsurface;j++)
10028                         {
10029                                 surface = rsurface.modelsurfaces + surfacelist[j];
10030                                 if (texture != surface->texture)
10031                                         break;
10032                                 texturesurfacelist[texturenumsurfaces++] = surface;
10033                         }
10034                 }
10035                 else
10036                 {
10037                         rsurface.lightmaptexture = surface->lightmaptexture;
10038                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10039                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10040                         for (;j < endsurface;j++)
10041                         {
10042                                 surface = rsurface.modelsurfaces + surfacelist[j];
10043                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10044                                         break;
10045                                 texturesurfacelist[texturenumsurfaces++] = surface;
10046                         }
10047                 }
10048                 // render the range of surfaces
10049                 if (ent == r_refdef.scene.worldentity)
10050                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10051                 else
10052                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10053         }
10054         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10055 }
10056
10057 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10058 {
10059         // transparent surfaces get pushed off into the transparent queue
10060         int surfacelistindex;
10061         const msurface_t *surface;
10062         vec3_t tempcenter, center;
10063         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10064         {
10065                 surface = texturesurfacelist[surfacelistindex];
10066                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10067                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10068                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10069                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10070                 if (queueentity->transparent_offset) // transparent offset
10071                 {
10072                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10073                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10074                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10075                 }
10076                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10077         }
10078 }
10079
10080 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10081 {
10082         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10083                 return;
10084         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10085                 return;
10086         RSurf_SetupDepthAndCulling();
10087         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10088         if (rsurface.batchvertex3fbuffer)
10089                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10090         else
10091                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10092         RSurf_DrawBatch();
10093 }
10094
10095 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10096 {
10097         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10098         CHECKGLERROR
10099         if (depthonly)
10100                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10101         else if (prepass)
10102         {
10103                 if (!rsurface.texture->currentnumlayers)
10104                         return;
10105                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10106                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10107                 else
10108                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10109         }
10110         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10111                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10112         else if (!rsurface.texture->currentnumlayers)
10113                 return;
10114         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10115         {
10116                 // in the deferred case, transparent surfaces were queued during prepass
10117                 if (!r_shadow_usingdeferredprepass)
10118                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10119         }
10120         else
10121         {
10122                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10123                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10124         }
10125         CHECKGLERROR
10126 }
10127
10128 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10129 {
10130         int i, j;
10131         texture_t *texture;
10132         R_FrameData_SetMark();
10133         // break the surface list down into batches by texture and use of lightmapping
10134         for (i = 0;i < numsurfaces;i = j)
10135         {
10136                 j = i + 1;
10137                 // texture is the base texture pointer, rsurface.texture is the
10138                 // current frame/skin the texture is directing us to use (for example
10139                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10140                 // use skin 1 instead)
10141                 texture = surfacelist[i]->texture;
10142                 rsurface.texture = R_GetCurrentTexture(texture);
10143                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10144                 {
10145                         // if this texture is not the kind we want, skip ahead to the next one
10146                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10147                                 ;
10148                         continue;
10149                 }
10150                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10151                 {
10152                         rsurface.lightmaptexture = NULL;
10153                         rsurface.deluxemaptexture = NULL;
10154                         rsurface.uselightmaptexture = false;
10155                         // simply scan ahead until we find a different texture or lightmap state
10156                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10157                                 ;
10158                 }
10159                 else
10160                 {
10161                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10162                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10163                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10164                         // simply scan ahead until we find a different texture or lightmap state
10165                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10166                                 ;
10167                 }
10168                 // render the range of surfaces
10169                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10170         }
10171         R_FrameData_ReturnToMark();
10172 }
10173
10174 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10175 {
10176         CHECKGLERROR
10177         if (depthonly)
10178                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10179         else if (prepass)
10180         {
10181                 if (!rsurface.texture->currentnumlayers)
10182                         return;
10183                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10184                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10185                 else
10186                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10187         }
10188         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10189                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10190         else if (!rsurface.texture->currentnumlayers)
10191                 return;
10192         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10193         {
10194                 // in the deferred case, transparent surfaces were queued during prepass
10195                 if (!r_shadow_usingdeferredprepass)
10196                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10197         }
10198         else
10199         {
10200                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10201                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10202         }
10203         CHECKGLERROR
10204 }
10205
10206 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10207 {
10208         int i, j;
10209         texture_t *texture;
10210         R_FrameData_SetMark();
10211         // break the surface list down into batches by texture and use of lightmapping
10212         for (i = 0;i < numsurfaces;i = j)
10213         {
10214                 j = i + 1;
10215                 // texture is the base texture pointer, rsurface.texture is the
10216                 // current frame/skin the texture is directing us to use (for example
10217                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10218                 // use skin 1 instead)
10219                 texture = surfacelist[i]->texture;
10220                 rsurface.texture = R_GetCurrentTexture(texture);
10221                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10222                 {
10223                         // if this texture is not the kind we want, skip ahead to the next one
10224                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10225                                 ;
10226                         continue;
10227                 }
10228                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10229                 {
10230                         rsurface.lightmaptexture = NULL;
10231                         rsurface.deluxemaptexture = NULL;
10232                         rsurface.uselightmaptexture = false;
10233                         // simply scan ahead until we find a different texture or lightmap state
10234                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10235                                 ;
10236                 }
10237                 else
10238                 {
10239                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10240                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10241                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10242                         // simply scan ahead until we find a different texture or lightmap state
10243                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10244                                 ;
10245                 }
10246                 // render the range of surfaces
10247                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10248         }
10249         R_FrameData_ReturnToMark();
10250 }
10251
10252 float locboxvertex3f[6*4*3] =
10253 {
10254         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10255         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10256         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10257         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10258         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10259         1,0,0, 0,0,0, 0,1,0, 1,1,0
10260 };
10261
10262 unsigned short locboxelements[6*2*3] =
10263 {
10264          0, 1, 2, 0, 2, 3,
10265          4, 5, 6, 4, 6, 7,
10266          8, 9,10, 8,10,11,
10267         12,13,14, 12,14,15,
10268         16,17,18, 16,18,19,
10269         20,21,22, 20,22,23
10270 };
10271
10272 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10273 {
10274         int i, j;
10275         cl_locnode_t *loc = (cl_locnode_t *)ent;
10276         vec3_t mins, size;
10277         float vertex3f[6*4*3];
10278         CHECKGLERROR
10279         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10280         GL_DepthMask(false);
10281         GL_DepthRange(0, 1);
10282         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10283         GL_DepthTest(true);
10284         GL_CullFace(GL_NONE);
10285         R_EntityMatrix(&identitymatrix);
10286
10287 //      R_Mesh_ResetTextureState();
10288
10289         i = surfacelist[0];
10290         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10291                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10292                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10293                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10294
10295         if (VectorCompare(loc->mins, loc->maxs))
10296         {
10297                 VectorSet(size, 2, 2, 2);
10298                 VectorMA(loc->mins, -0.5f, size, mins);
10299         }
10300         else
10301         {
10302                 VectorCopy(loc->mins, mins);
10303                 VectorSubtract(loc->maxs, loc->mins, size);
10304         }
10305
10306         for (i = 0;i < 6*4*3;)
10307                 for (j = 0;j < 3;j++, i++)
10308                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10309
10310         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10311         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10312         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10313 }
10314
10315 void R_DrawLocs(void)
10316 {
10317         int index;
10318         cl_locnode_t *loc, *nearestloc;
10319         vec3_t center;
10320         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10321         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10322         {
10323                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10324                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10325         }
10326 }
10327
10328 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10329 {
10330         if (decalsystem->decals)
10331                 Mem_Free(decalsystem->decals);
10332         memset(decalsystem, 0, sizeof(*decalsystem));
10333 }
10334
10335 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)
10336 {
10337         tridecal_t *decal;
10338         tridecal_t *decals;
10339         int i;
10340
10341         // expand or initialize the system
10342         if (decalsystem->maxdecals <= decalsystem->numdecals)
10343         {
10344                 decalsystem_t old = *decalsystem;
10345                 qboolean useshortelements;
10346                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10347                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10348                 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)));
10349                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10350                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10351                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10352                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10353                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10354                 if (decalsystem->numdecals)
10355                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10356                 if (old.decals)
10357                         Mem_Free(old.decals);
10358                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10359                         decalsystem->element3i[i] = i;
10360                 if (useshortelements)
10361                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10362                                 decalsystem->element3s[i] = i;
10363         }
10364
10365         // grab a decal and search for another free slot for the next one
10366         decals = decalsystem->decals;
10367         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10368         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10369                 ;
10370         decalsystem->freedecal = i;
10371         if (decalsystem->numdecals <= i)
10372                 decalsystem->numdecals = i + 1;
10373
10374         // initialize the decal
10375         decal->lived = 0;
10376         decal->triangleindex = triangleindex;
10377         decal->surfaceindex = surfaceindex;
10378         decal->decalsequence = decalsequence;
10379         decal->color4f[0][0] = c0[0];
10380         decal->color4f[0][1] = c0[1];
10381         decal->color4f[0][2] = c0[2];
10382         decal->color4f[0][3] = 1;
10383         decal->color4f[1][0] = c1[0];
10384         decal->color4f[1][1] = c1[1];
10385         decal->color4f[1][2] = c1[2];
10386         decal->color4f[1][3] = 1;
10387         decal->color4f[2][0] = c2[0];
10388         decal->color4f[2][1] = c2[1];
10389         decal->color4f[2][2] = c2[2];
10390         decal->color4f[2][3] = 1;
10391         decal->vertex3f[0][0] = v0[0];
10392         decal->vertex3f[0][1] = v0[1];
10393         decal->vertex3f[0][2] = v0[2];
10394         decal->vertex3f[1][0] = v1[0];
10395         decal->vertex3f[1][1] = v1[1];
10396         decal->vertex3f[1][2] = v1[2];
10397         decal->vertex3f[2][0] = v2[0];
10398         decal->vertex3f[2][1] = v2[1];
10399         decal->vertex3f[2][2] = v2[2];
10400         decal->texcoord2f[0][0] = t0[0];
10401         decal->texcoord2f[0][1] = t0[1];
10402         decal->texcoord2f[1][0] = t1[0];
10403         decal->texcoord2f[1][1] = t1[1];
10404         decal->texcoord2f[2][0] = t2[0];
10405         decal->texcoord2f[2][1] = t2[1];
10406         TriangleNormal(v0, v1, v2, decal->plane);
10407         VectorNormalize(decal->plane);
10408         decal->plane[3] = DotProduct(v0, decal->plane);
10409 }
10410
10411 extern cvar_t cl_decals_bias;
10412 extern cvar_t cl_decals_models;
10413 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10414 // baseparms, parms, temps
10415 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)
10416 {
10417         int cornerindex;
10418         int index;
10419         float v[9][3];
10420         const float *vertex3f;
10421         const float *normal3f;
10422         int numpoints;
10423         float points[2][9][3];
10424         float temp[3];
10425         float tc[9][2];
10426         float f;
10427         float c[9][4];
10428         const int *e;
10429
10430         e = rsurface.modelelement3i + 3*triangleindex;
10431
10432         vertex3f = rsurface.modelvertex3f;
10433         normal3f = rsurface.modelnormal3f;
10434
10435         if (normal3f)
10436         {
10437                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10438                 {
10439                         index = 3*e[cornerindex];
10440                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10441                 }
10442         }
10443         else
10444         {
10445                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10446                 {
10447                         index = 3*e[cornerindex];
10448                         VectorCopy(vertex3f + index, v[cornerindex]);
10449                 }
10450         }
10451
10452         // cull backfaces
10453         //TriangleNormal(v[0], v[1], v[2], normal);
10454         //if (DotProduct(normal, localnormal) < 0.0f)
10455         //      continue;
10456         // clip by each of the box planes formed from the projection matrix
10457         // if anything survives, we emit the decal
10458         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]);
10459         if (numpoints < 3)
10460                 return;
10461         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]);
10462         if (numpoints < 3)
10463                 return;
10464         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]);
10465         if (numpoints < 3)
10466                 return;
10467         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]);
10468         if (numpoints < 3)
10469                 return;
10470         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]);
10471         if (numpoints < 3)
10472                 return;
10473         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]);
10474         if (numpoints < 3)
10475                 return;
10476         // some part of the triangle survived, so we have to accept it...
10477         if (dynamic)
10478         {
10479                 // dynamic always uses the original triangle
10480                 numpoints = 3;
10481                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10482                 {
10483                         index = 3*e[cornerindex];
10484                         VectorCopy(vertex3f + index, v[cornerindex]);
10485                 }
10486         }
10487         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10488         {
10489                 // convert vertex positions to texcoords
10490                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10491                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10492                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10493                 // calculate distance fade from the projection origin
10494                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10495                 f = bound(0.0f, f, 1.0f);
10496                 c[cornerindex][0] = r * f;
10497                 c[cornerindex][1] = g * f;
10498                 c[cornerindex][2] = b * f;
10499                 c[cornerindex][3] = 1.0f;
10500                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10501         }
10502         if (dynamic)
10503                 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);
10504         else
10505                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10506                         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);
10507 }
10508 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)
10509 {
10510         matrix4x4_t projection;
10511         decalsystem_t *decalsystem;
10512         qboolean dynamic;
10513         dp_model_t *model;
10514         const msurface_t *surface;
10515         const msurface_t *surfaces;
10516         const int *surfacelist;
10517         const texture_t *texture;
10518         int numtriangles;
10519         int numsurfacelist;
10520         int surfacelistindex;
10521         int surfaceindex;
10522         int triangleindex;
10523         float localorigin[3];
10524         float localnormal[3];
10525         float localmins[3];
10526         float localmaxs[3];
10527         float localsize;
10528         //float normal[3];
10529         float planes[6][4];
10530         float angles[3];
10531         bih_t *bih;
10532         int bih_triangles_count;
10533         int bih_triangles[256];
10534         int bih_surfaces[256];
10535
10536         decalsystem = &ent->decalsystem;
10537         model = ent->model;
10538         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10539         {
10540                 R_DecalSystem_Reset(&ent->decalsystem);
10541                 return;
10542         }
10543
10544         if (!model->brush.data_leafs && !cl_decals_models.integer)
10545         {
10546                 if (decalsystem->model)
10547                         R_DecalSystem_Reset(decalsystem);
10548                 return;
10549         }
10550
10551         if (decalsystem->model != model)
10552                 R_DecalSystem_Reset(decalsystem);
10553         decalsystem->model = model;
10554
10555         RSurf_ActiveModelEntity(ent, true, false, false);
10556
10557         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10558         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10559         VectorNormalize(localnormal);
10560         localsize = worldsize*rsurface.inversematrixscale;
10561         localmins[0] = localorigin[0] - localsize;
10562         localmins[1] = localorigin[1] - localsize;
10563         localmins[2] = localorigin[2] - localsize;
10564         localmaxs[0] = localorigin[0] + localsize;
10565         localmaxs[1] = localorigin[1] + localsize;
10566         localmaxs[2] = localorigin[2] + localsize;
10567
10568         //VectorCopy(localnormal, planes[4]);
10569         //VectorVectors(planes[4], planes[2], planes[0]);
10570         AnglesFromVectors(angles, localnormal, NULL, false);
10571         AngleVectors(angles, planes[0], planes[2], planes[4]);
10572         VectorNegate(planes[0], planes[1]);
10573         VectorNegate(planes[2], planes[3]);
10574         VectorNegate(planes[4], planes[5]);
10575         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10576         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10577         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10578         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10579         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10580         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10581
10582 #if 1
10583 // works
10584 {
10585         matrix4x4_t forwardprojection;
10586         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10587         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10588 }
10589 #else
10590 // broken
10591 {
10592         float projectionvector[4][3];
10593         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10594         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10595         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10596         projectionvector[0][0] = planes[0][0] * ilocalsize;
10597         projectionvector[0][1] = planes[1][0] * ilocalsize;
10598         projectionvector[0][2] = planes[2][0] * ilocalsize;
10599         projectionvector[1][0] = planes[0][1] * ilocalsize;
10600         projectionvector[1][1] = planes[1][1] * ilocalsize;
10601         projectionvector[1][2] = planes[2][1] * ilocalsize;
10602         projectionvector[2][0] = planes[0][2] * ilocalsize;
10603         projectionvector[2][1] = planes[1][2] * ilocalsize;
10604         projectionvector[2][2] = planes[2][2] * ilocalsize;
10605         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10606         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10607         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10608         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10609 }
10610 #endif
10611
10612         dynamic = model->surfmesh.isanimated;
10613         numsurfacelist = model->nummodelsurfaces;
10614         surfacelist = model->sortedmodelsurfaces;
10615         surfaces = model->data_surfaces;
10616
10617         bih = NULL;
10618         bih_triangles_count = -1;
10619         if(!dynamic)
10620         {
10621                 if(model->render_bih.numleafs)
10622                         bih = &model->render_bih;
10623                 else if(model->collision_bih.numleafs)
10624                         bih = &model->collision_bih;
10625         }
10626         if(bih)
10627                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10628         if(bih_triangles_count == 0)
10629                 return;
10630         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10631                 return;
10632         if(bih_triangles_count > 0)
10633         {
10634                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10635                 {
10636                         surfaceindex = bih_surfaces[triangleindex];
10637                         surface = surfaces + surfaceindex;
10638                         texture = surface->texture;
10639                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10640                                 continue;
10641                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10642                                 continue;
10643                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10644                 }
10645         }
10646         else
10647         {
10648                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10649                 {
10650                         surfaceindex = surfacelist[surfacelistindex];
10651                         surface = surfaces + surfaceindex;
10652                         // check cull box first because it rejects more than any other check
10653                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10654                                 continue;
10655                         // skip transparent surfaces
10656                         texture = surface->texture;
10657                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10658                                 continue;
10659                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10660                                 continue;
10661                         numtriangles = surface->num_triangles;
10662                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10663                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10664                 }
10665         }
10666 }
10667
10668 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10669 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)
10670 {
10671         int renderentityindex;
10672         float worldmins[3];
10673         float worldmaxs[3];
10674         entity_render_t *ent;
10675
10676         if (!cl_decals_newsystem.integer)
10677                 return;
10678
10679         worldmins[0] = worldorigin[0] - worldsize;
10680         worldmins[1] = worldorigin[1] - worldsize;
10681         worldmins[2] = worldorigin[2] - worldsize;
10682         worldmaxs[0] = worldorigin[0] + worldsize;
10683         worldmaxs[1] = worldorigin[1] + worldsize;
10684         worldmaxs[2] = worldorigin[2] + worldsize;
10685
10686         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10687
10688         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10689         {
10690                 ent = r_refdef.scene.entities[renderentityindex];
10691                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10692                         continue;
10693
10694                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10695         }
10696 }
10697
10698 typedef struct r_decalsystem_splatqueue_s
10699 {
10700         vec3_t worldorigin;
10701         vec3_t worldnormal;
10702         float color[4];
10703         float tcrange[4];
10704         float worldsize;
10705         int decalsequence;
10706 }
10707 r_decalsystem_splatqueue_t;
10708
10709 int r_decalsystem_numqueued = 0;
10710 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10711
10712 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)
10713 {
10714         r_decalsystem_splatqueue_t *queue;
10715
10716         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10717                 return;
10718
10719         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10720         VectorCopy(worldorigin, queue->worldorigin);
10721         VectorCopy(worldnormal, queue->worldnormal);
10722         Vector4Set(queue->color, r, g, b, a);
10723         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10724         queue->worldsize = worldsize;
10725         queue->decalsequence = cl.decalsequence++;
10726 }
10727
10728 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10729 {
10730         int i;
10731         r_decalsystem_splatqueue_t *queue;
10732
10733         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10734                 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);
10735         r_decalsystem_numqueued = 0;
10736 }
10737
10738 extern cvar_t cl_decals_max;
10739 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10740 {
10741         int i;
10742         decalsystem_t *decalsystem = &ent->decalsystem;
10743         int numdecals;
10744         int killsequence;
10745         tridecal_t *decal;
10746         float frametime;
10747         float lifetime;
10748
10749         if (!decalsystem->numdecals)
10750                 return;
10751
10752         if (r_showsurfaces.integer)
10753                 return;
10754
10755         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10756         {
10757                 R_DecalSystem_Reset(decalsystem);
10758                 return;
10759         }
10760
10761         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10762         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10763
10764         if (decalsystem->lastupdatetime)
10765                 frametime = (cl.time - decalsystem->lastupdatetime);
10766         else
10767                 frametime = 0;
10768         decalsystem->lastupdatetime = cl.time;
10769         decal = decalsystem->decals;
10770         numdecals = decalsystem->numdecals;
10771
10772         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10773         {
10774                 if (decal->color4f[0][3])
10775                 {
10776                         decal->lived += frametime;
10777                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10778                         {
10779                                 memset(decal, 0, sizeof(*decal));
10780                                 if (decalsystem->freedecal > i)
10781                                         decalsystem->freedecal = i;
10782                         }
10783                 }
10784         }
10785         decal = decalsystem->decals;
10786         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10787                 numdecals--;
10788
10789         // collapse the array by shuffling the tail decals into the gaps
10790         for (;;)
10791         {
10792                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10793                         decalsystem->freedecal++;
10794                 if (decalsystem->freedecal == numdecals)
10795                         break;
10796                 decal[decalsystem->freedecal] = decal[--numdecals];
10797         }
10798
10799         decalsystem->numdecals = numdecals;
10800
10801         if (numdecals <= 0)
10802         {
10803                 // if there are no decals left, reset decalsystem
10804                 R_DecalSystem_Reset(decalsystem);
10805         }
10806 }
10807
10808 extern skinframe_t *decalskinframe;
10809 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10810 {
10811         int i;
10812         decalsystem_t *decalsystem = &ent->decalsystem;
10813         int numdecals;
10814         tridecal_t *decal;
10815         float faderate;
10816         float alpha;
10817         float *v3f;
10818         float *c4f;
10819         float *t2f;
10820         const int *e;
10821         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10822         int numtris = 0;
10823
10824         numdecals = decalsystem->numdecals;
10825         if (!numdecals)
10826                 return;
10827
10828         if (r_showsurfaces.integer)
10829                 return;
10830
10831         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10832         {
10833                 R_DecalSystem_Reset(decalsystem);
10834                 return;
10835         }
10836
10837         // if the model is static it doesn't matter what value we give for
10838         // wantnormals and wanttangents, so this logic uses only rules applicable
10839         // to a model, knowing that they are meaningless otherwise
10840         if (ent == r_refdef.scene.worldentity)
10841                 RSurf_ActiveWorldEntity();
10842         else
10843                 RSurf_ActiveModelEntity(ent, false, false, false);
10844
10845         decalsystem->lastupdatetime = cl.time;
10846         decal = decalsystem->decals;
10847
10848         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10849
10850         // update vertex positions for animated models
10851         v3f = decalsystem->vertex3f;
10852         c4f = decalsystem->color4f;
10853         t2f = decalsystem->texcoord2f;
10854         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10855         {
10856                 if (!decal->color4f[0][3])
10857                         continue;
10858
10859                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10860                         continue;
10861
10862                 // skip backfaces
10863                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10864                         continue;
10865
10866                 // update color values for fading decals
10867                 if (decal->lived >= cl_decals_time.value)
10868                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10869                 else
10870                         alpha = 1.0f;
10871
10872                 c4f[ 0] = decal->color4f[0][0] * alpha;
10873                 c4f[ 1] = decal->color4f[0][1] * alpha;
10874                 c4f[ 2] = decal->color4f[0][2] * alpha;
10875                 c4f[ 3] = 1;
10876                 c4f[ 4] = decal->color4f[1][0] * alpha;
10877                 c4f[ 5] = decal->color4f[1][1] * alpha;
10878                 c4f[ 6] = decal->color4f[1][2] * alpha;
10879                 c4f[ 7] = 1;
10880                 c4f[ 8] = decal->color4f[2][0] * alpha;
10881                 c4f[ 9] = decal->color4f[2][1] * alpha;
10882                 c4f[10] = decal->color4f[2][2] * alpha;
10883                 c4f[11] = 1;
10884
10885                 t2f[0] = decal->texcoord2f[0][0];
10886                 t2f[1] = decal->texcoord2f[0][1];
10887                 t2f[2] = decal->texcoord2f[1][0];
10888                 t2f[3] = decal->texcoord2f[1][1];
10889                 t2f[4] = decal->texcoord2f[2][0];
10890                 t2f[5] = decal->texcoord2f[2][1];
10891
10892                 // update vertex positions for animated models
10893                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10894                 {
10895                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10896                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10897                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10898                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10899                 }
10900                 else
10901                 {
10902                         VectorCopy(decal->vertex3f[0], v3f);
10903                         VectorCopy(decal->vertex3f[1], v3f + 3);
10904                         VectorCopy(decal->vertex3f[2], v3f + 6);
10905                 }
10906
10907                 if (r_refdef.fogenabled)
10908                 {
10909                         alpha = RSurf_FogVertex(v3f);
10910                         VectorScale(c4f, alpha, c4f);
10911                         alpha = RSurf_FogVertex(v3f + 3);
10912                         VectorScale(c4f + 4, alpha, c4f + 4);
10913                         alpha = RSurf_FogVertex(v3f + 6);
10914                         VectorScale(c4f + 8, alpha, c4f + 8);
10915                 }
10916
10917                 v3f += 9;
10918                 c4f += 12;
10919                 t2f += 6;
10920                 numtris++;
10921         }
10922
10923         if (numtris > 0)
10924         {
10925                 r_refdef.stats.drawndecals += numtris;
10926
10927                 // now render the decals all at once
10928                 // (this assumes they all use one particle font texture!)
10929                 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);
10930 //              R_Mesh_ResetTextureState();
10931                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10932                 GL_DepthMask(false);
10933                 GL_DepthRange(0, 1);
10934                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10935                 GL_DepthTest(true);
10936                 GL_CullFace(GL_NONE);
10937                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10938                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10939                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10940         }
10941 }
10942
10943 static void R_DrawModelDecals(void)
10944 {
10945         int i, numdecals;
10946
10947         // fade faster when there are too many decals
10948         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10949         for (i = 0;i < r_refdef.scene.numentities;i++)
10950                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10951
10952         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10953         for (i = 0;i < r_refdef.scene.numentities;i++)
10954                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10955                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10956
10957         R_DecalSystem_ApplySplatEntitiesQueue();
10958
10959         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10960         for (i = 0;i < r_refdef.scene.numentities;i++)
10961                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10962
10963         r_refdef.stats.totaldecals += numdecals;
10964
10965         if (r_showsurfaces.integer)
10966                 return;
10967
10968         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10969
10970         for (i = 0;i < r_refdef.scene.numentities;i++)
10971         {
10972                 if (!r_refdef.viewcache.entityvisible[i])
10973                         continue;
10974                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10975                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10976         }
10977 }
10978
10979 extern cvar_t mod_collision_bih;
10980 void R_DrawDebugModel(void)
10981 {
10982         entity_render_t *ent = rsurface.entity;
10983         int i, j, k, l, flagsmask;
10984         const msurface_t *surface;
10985         dp_model_t *model = ent->model;
10986         vec3_t v;
10987
10988         switch(vid.renderpath)
10989         {
10990         case RENDERPATH_GL11:
10991         case RENDERPATH_GL13:
10992         case RENDERPATH_GL20:
10993                 break;
10994         case RENDERPATH_D3D9:
10995                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10996                 return;
10997         case RENDERPATH_D3D10:
10998                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10999                 return;
11000         case RENDERPATH_D3D11:
11001                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11002                 return;
11003         case RENDERPATH_SOFT:
11004                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11005                 return;
11006         case RENDERPATH_GLES2:
11007                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11008                 return;
11009         }
11010
11011         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11012
11013 //      R_Mesh_ResetTextureState();
11014         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11015         GL_DepthRange(0, 1);
11016         GL_DepthTest(!r_showdisabledepthtest.integer);
11017         GL_DepthMask(false);
11018         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11019
11020         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11021         {
11022                 int triangleindex;
11023                 int bihleafindex;
11024                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11025                 const q3mbrush_t *brush;
11026                 const bih_t *bih = &model->collision_bih;
11027                 const bih_leaf_t *bihleaf;
11028                 float vertex3f[3][3];
11029                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11030                 cullbox = false;
11031                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11032                 {
11033                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11034                                 continue;
11035                         switch (bihleaf->type)
11036                         {
11037                         case BIH_BRUSH:
11038                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11039                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11040                                 {
11041                                         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);
11042                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11043                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11044                                 }
11045                                 break;
11046                         case BIH_COLLISIONTRIANGLE:
11047                                 triangleindex = bihleaf->itemindex;
11048                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11049                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11050                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11051                                 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);
11052                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11053                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11054                                 break;
11055                         case BIH_RENDERTRIANGLE:
11056                                 triangleindex = bihleaf->itemindex;
11057                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11058                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11059                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11060                                 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);
11061                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11062                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11063                                 break;
11064                         }
11065                 }
11066         }
11067
11068         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11069
11070         if (r_showtris.integer || (r_shownormals.value != 0))
11071         {
11072                 if (r_showdisabledepthtest.integer)
11073                 {
11074                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11075                         GL_DepthMask(false);
11076                 }
11077                 else
11078                 {
11079                         GL_BlendFunc(GL_ONE, GL_ZERO);
11080                         GL_DepthMask(true);
11081                 }
11082                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11083                 {
11084                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11085                                 continue;
11086                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11087                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11088                         {
11089                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11090                                 if (r_showtris.value > 0)
11091                                 {
11092                                         if (!rsurface.texture->currentlayers->depthmask)
11093                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11094                                         else if (ent == r_refdef.scene.worldentity)
11095                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11096                                         else
11097                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11098                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11099                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11100                                         RSurf_DrawBatch();
11101                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11102                                         CHECKGLERROR
11103                                 }
11104                                 if (r_shownormals.value < 0)
11105                                 {
11106                                         qglBegin(GL_LINES);
11107                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11108                                         {
11109                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11110                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11111                                                 qglVertex3f(v[0], v[1], v[2]);
11112                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11113                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11114                                                 qglVertex3f(v[0], v[1], v[2]);
11115                                         }
11116                                         qglEnd();
11117                                         CHECKGLERROR
11118                                 }
11119                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11120                                 {
11121                                         qglBegin(GL_LINES);
11122                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11123                                         {
11124                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11125                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11126                                                 qglVertex3f(v[0], v[1], v[2]);
11127                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11128                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11129                                                 qglVertex3f(v[0], v[1], v[2]);
11130                                         }
11131                                         qglEnd();
11132                                         CHECKGLERROR
11133                                         qglBegin(GL_LINES);
11134                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11135                                         {
11136                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11137                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11138                                                 qglVertex3f(v[0], v[1], v[2]);
11139                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11140                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11141                                                 qglVertex3f(v[0], v[1], v[2]);
11142                                         }
11143                                         qglEnd();
11144                                         CHECKGLERROR
11145                                         qglBegin(GL_LINES);
11146                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11147                                         {
11148                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11149                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11150                                                 qglVertex3f(v[0], v[1], v[2]);
11151                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11152                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11153                                                 qglVertex3f(v[0], v[1], v[2]);
11154                                         }
11155                                         qglEnd();
11156                                         CHECKGLERROR
11157                                 }
11158                         }
11159                 }
11160                 rsurface.texture = NULL;
11161         }
11162 }
11163
11164 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11165 int r_maxsurfacelist = 0;
11166 const msurface_t **r_surfacelist = NULL;
11167 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11168 {
11169         int i, j, endj, flagsmask;
11170         dp_model_t *model = r_refdef.scene.worldmodel;
11171         msurface_t *surfaces;
11172         unsigned char *update;
11173         int numsurfacelist = 0;
11174         if (model == NULL)
11175                 return;
11176
11177         if (r_maxsurfacelist < model->num_surfaces)
11178         {
11179                 r_maxsurfacelist = model->num_surfaces;
11180                 if (r_surfacelist)
11181                         Mem_Free((msurface_t**)r_surfacelist);
11182                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11183         }
11184
11185         RSurf_ActiveWorldEntity();
11186
11187         surfaces = model->data_surfaces;
11188         update = model->brushq1.lightmapupdateflags;
11189
11190         // update light styles on this submodel
11191         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11192         {
11193                 model_brush_lightstyleinfo_t *style;
11194                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11195                 {
11196                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11197                         {
11198                                 int *list = style->surfacelist;
11199                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11200                                 for (j = 0;j < style->numsurfaces;j++)
11201                                         update[list[j]] = true;
11202                         }
11203                 }
11204         }
11205
11206         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11207
11208         if (debug)
11209         {
11210                 R_DrawDebugModel();
11211                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11212                 return;
11213         }
11214
11215         rsurface.lightmaptexture = NULL;
11216         rsurface.deluxemaptexture = NULL;
11217         rsurface.uselightmaptexture = false;
11218         rsurface.texture = NULL;
11219         rsurface.rtlight = NULL;
11220         numsurfacelist = 0;
11221         // add visible surfaces to draw list
11222         for (i = 0;i < model->nummodelsurfaces;i++)
11223         {
11224                 j = model->sortedmodelsurfaces[i];
11225                 if (r_refdef.viewcache.world_surfacevisible[j])
11226                         r_surfacelist[numsurfacelist++] = surfaces + j;
11227         }
11228         // update lightmaps if needed
11229         if (model->brushq1.firstrender)
11230         {
11231                 model->brushq1.firstrender = false;
11232                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11233                         if (update[j])
11234                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11235         }
11236         else if (update)
11237         {
11238                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11239                         if (r_refdef.viewcache.world_surfacevisible[j])
11240                                 if (update[j])
11241                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11242         }
11243         // don't do anything if there were no surfaces
11244         if (!numsurfacelist)
11245         {
11246                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11247                 return;
11248         }
11249         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11250
11251         // add to stats if desired
11252         if (r_speeds.integer && !skysurfaces && !depthonly)
11253         {
11254                 r_refdef.stats.world_surfaces += numsurfacelist;
11255                 for (j = 0;j < numsurfacelist;j++)
11256                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11257         }
11258
11259         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11260 }
11261
11262 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11263 {
11264         int i, j, endj, flagsmask;
11265         dp_model_t *model = ent->model;
11266         msurface_t *surfaces;
11267         unsigned char *update;
11268         int numsurfacelist = 0;
11269         if (model == NULL)
11270                 return;
11271
11272         if (r_maxsurfacelist < model->num_surfaces)
11273         {
11274                 r_maxsurfacelist = model->num_surfaces;
11275                 if (r_surfacelist)
11276                         Mem_Free((msurface_t **)r_surfacelist);
11277                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11278         }
11279
11280         // if the model is static it doesn't matter what value we give for
11281         // wantnormals and wanttangents, so this logic uses only rules applicable
11282         // to a model, knowing that they are meaningless otherwise
11283         if (ent == r_refdef.scene.worldentity)
11284                 RSurf_ActiveWorldEntity();
11285         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11286                 RSurf_ActiveModelEntity(ent, false, false, false);
11287         else if (prepass)
11288                 RSurf_ActiveModelEntity(ent, true, true, true);
11289         else if (depthonly)
11290         {
11291                 switch (vid.renderpath)
11292                 {
11293                 case RENDERPATH_GL20:
11294                 case RENDERPATH_D3D9:
11295                 case RENDERPATH_D3D10:
11296                 case RENDERPATH_D3D11:
11297                 case RENDERPATH_SOFT:
11298                 case RENDERPATH_GLES2:
11299                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11300                         break;
11301                 case RENDERPATH_GL13:
11302                 case RENDERPATH_GL11:
11303                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11304                         break;
11305                 }
11306         }
11307         else
11308         {
11309                 switch (vid.renderpath)
11310                 {
11311                 case RENDERPATH_GL20:
11312                 case RENDERPATH_D3D9:
11313                 case RENDERPATH_D3D10:
11314                 case RENDERPATH_D3D11:
11315                 case RENDERPATH_SOFT:
11316                 case RENDERPATH_GLES2:
11317                         RSurf_ActiveModelEntity(ent, true, true, false);
11318                         break;
11319                 case RENDERPATH_GL13:
11320                 case RENDERPATH_GL11:
11321                         RSurf_ActiveModelEntity(ent, true, false, false);
11322                         break;
11323                 }
11324         }
11325
11326         surfaces = model->data_surfaces;
11327         update = model->brushq1.lightmapupdateflags;
11328
11329         // update light styles
11330         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11331         {
11332                 model_brush_lightstyleinfo_t *style;
11333                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11334                 {
11335                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11336                         {
11337                                 int *list = style->surfacelist;
11338                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11339                                 for (j = 0;j < style->numsurfaces;j++)
11340                                         update[list[j]] = true;
11341                         }
11342                 }
11343         }
11344
11345         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11346
11347         if (debug)
11348         {
11349                 R_DrawDebugModel();
11350                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11351                 return;
11352         }
11353
11354         rsurface.lightmaptexture = NULL;
11355         rsurface.deluxemaptexture = NULL;
11356         rsurface.uselightmaptexture = false;
11357         rsurface.texture = NULL;
11358         rsurface.rtlight = NULL;
11359         numsurfacelist = 0;
11360         // add visible surfaces to draw list
11361         for (i = 0;i < model->nummodelsurfaces;i++)
11362                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11363         // don't do anything if there were no surfaces
11364         if (!numsurfacelist)
11365         {
11366                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11367                 return;
11368         }
11369         // update lightmaps if needed
11370         if (update)
11371         {
11372                 int updated = 0;
11373                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11374                 {
11375                         if (update[j])
11376                         {
11377                                 updated++;
11378                                 R_BuildLightMap(ent, surfaces + j);
11379                         }
11380                 }
11381         }
11382         if (update)
11383                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11384                         if (update[j])
11385                                 R_BuildLightMap(ent, surfaces + j);
11386         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11387
11388         // add to stats if desired
11389         if (r_speeds.integer && !skysurfaces && !depthonly)
11390         {
11391                 r_refdef.stats.entities_surfaces += numsurfacelist;
11392                 for (j = 0;j < numsurfacelist;j++)
11393                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11394         }
11395
11396         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11397 }
11398
11399 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11400 {
11401         static texture_t texture;
11402         static msurface_t surface;
11403         const msurface_t *surfacelist = &surface;
11404
11405         // fake enough texture and surface state to render this geometry
11406
11407         texture.update_lastrenderframe = -1; // regenerate this texture
11408         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11409         texture.currentskinframe = skinframe;
11410         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11411         texture.offsetmapping = OFFSETMAPPING_OFF;
11412         texture.offsetscale = 1;
11413         texture.specularscalemod = 1;
11414         texture.specularpowermod = 1;
11415
11416         surface.texture = &texture;
11417         surface.num_triangles = numtriangles;
11418         surface.num_firsttriangle = firsttriangle;
11419         surface.num_vertices = numvertices;
11420         surface.num_firstvertex = firstvertex;
11421
11422         // now render it
11423         rsurface.texture = R_GetCurrentTexture(surface.texture);
11424         rsurface.lightmaptexture = NULL;
11425         rsurface.deluxemaptexture = NULL;
11426         rsurface.uselightmaptexture = false;
11427         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11428 }
11429
11430 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)
11431 {
11432         static msurface_t surface;
11433         const msurface_t *surfacelist = &surface;
11434
11435         // fake enough texture and surface state to render this geometry
11436         surface.texture = texture;
11437         surface.num_triangles = numtriangles;
11438         surface.num_firsttriangle = firsttriangle;
11439         surface.num_vertices = numvertices;
11440         surface.num_firstvertex = firstvertex;
11441
11442         // now render it
11443         rsurface.texture = R_GetCurrentTexture(surface.texture);
11444         rsurface.lightmaptexture = NULL;
11445         rsurface.deluxemaptexture = NULL;
11446         rsurface.uselightmaptexture = false;
11447         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11448 }