]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
added r_showoverdraw cvar which allows you to see how many draws per
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
74 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
75 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
76 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
77 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
78 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
80 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
81 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
82 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
83 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
84 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
85 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
86 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
87 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
88 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
89 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
90 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
91 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
92 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
93 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
94 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
95 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
96 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97
98 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
99 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
100 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101
102 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
103 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
104 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
105 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
106 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
107 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
108 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
109 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
110 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
111 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
112 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
113 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
114 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
116 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
118 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
119 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
120 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
121 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
122
123 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
124 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
125 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
126 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
127 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
128 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
129 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
130 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
131
132 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
133 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
134
135 cvar_t r_texture_sRGB_2d = {0, "r_texture_sRGB_2d", "0", "load textures as sRGB"};
136 cvar_t r_texture_sRGB_skin_diffuse = {0, "r_texture_sRGB_skin_diffuse", "0", "load textures as sRGB"};
137 cvar_t r_texture_sRGB_skin_gloss = {0, "r_texture_sRGB_skin_gloss", "0", "load textures as sRGB"};
138 cvar_t r_texture_sRGB_skin_glow = {0, "r_texture_sRGB_skin_glow", "0", "load textures as sRGB"};
139 cvar_t r_texture_sRGB_skin_reflect = {0, "r_texture_sRGB_skin_reflect", "0", "load textures as sRGB"};
140 cvar_t r_texture_sRGB_cubemap = {0, "r_texture_sRGB_cubemap", "0", "load textures as sRGB"};
141 cvar_t r_texture_sRGB_skybox = {0, "r_texture_sRGB_skybox", "0", "load textures as sRGB"};
142
143 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
144 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
145 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
146
147 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
148 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
149 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
150 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
151 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
152 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
153 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
154 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
155
156 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
157 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
158 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
159 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
160 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
161 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
162 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
163 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
164 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
165 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
168 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
169 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
170 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
171 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
172
173 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
174 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
175 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
176 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
177 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
178 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
179
180 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
181 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
182 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
183 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
184
185 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
186 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
187 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
188 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
189 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
190 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
191 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
192
193 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
194 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
195 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
196 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
197 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
198 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
199 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
200 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
201 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
202 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
203
204 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
205
206 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
207
208 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
209
210 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
211 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
212 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
213 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
214 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
215 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
216 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
217 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
218 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
219
220 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
221 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
222
223 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
224
225 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
226
227 extern cvar_t v_glslgamma;
228
229 extern qboolean v_flipped_state;
230
231 static struct r_bloomstate_s
232 {
233         qboolean enabled;
234         qboolean hdr;
235
236         int bloomwidth, bloomheight;
237
238         textype_t texturetype;
239         int viewfbo; // used to check if r_viewfbo cvar has changed
240
241         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
242         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
243         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
244
245         int screentexturewidth, screentextureheight;
246         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
247
248         int bloomtexturewidth, bloomtextureheight;
249         rtexture_t *texture_bloom;
250
251         // arrays for rendering the screen passes
252         float screentexcoord2f[8];
253         float bloomtexcoord2f[8];
254         float offsettexcoord2f[8];
255
256         r_viewport_t viewport;
257 }
258 r_bloomstate;
259
260 r_waterstate_t r_waterstate;
261
262 /// shadow volume bsp struct with automatically growing nodes buffer
263 svbsp_t r_svbsp;
264
265 rtexture_t *r_texture_blanknormalmap;
266 rtexture_t *r_texture_white;
267 rtexture_t *r_texture_grey128;
268 rtexture_t *r_texture_black;
269 rtexture_t *r_texture_notexture;
270 rtexture_t *r_texture_whitecube;
271 rtexture_t *r_texture_normalizationcube;
272 rtexture_t *r_texture_fogattenuation;
273 rtexture_t *r_texture_fogheighttexture;
274 rtexture_t *r_texture_gammaramps;
275 unsigned int r_texture_gammaramps_serial;
276 //rtexture_t *r_texture_fogintensity;
277 rtexture_t *r_texture_reflectcube;
278
279 // TODO: hash lookups?
280 typedef struct cubemapinfo_s
281 {
282         char basename[64];
283         rtexture_t *texture;
284 }
285 cubemapinfo_t;
286
287 int r_texture_numcubemaps;
288 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
289
290 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
291 unsigned int r_numqueries;
292 unsigned int r_maxqueries;
293
294 typedef struct r_qwskincache_s
295 {
296         char name[MAX_QPATH];
297         skinframe_t *skinframe;
298 }
299 r_qwskincache_t;
300
301 static r_qwskincache_t *r_qwskincache;
302 static int r_qwskincache_size;
303
304 /// vertex coordinates for a quad that covers the screen exactly
305 extern const float r_screenvertex3f[12];
306 extern const float r_d3dscreenvertex3f[12];
307 const float r_screenvertex3f[12] =
308 {
309         0, 0, 0,
310         1, 0, 0,
311         1, 1, 0,
312         0, 1, 0
313 };
314 const float r_d3dscreenvertex3f[12] =
315 {
316         0, 1, 0,
317         1, 1, 0,
318         1, 0, 0,
319         0, 0, 0
320 };
321
322 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
323 {
324         int i;
325         for (i = 0;i < verts;i++)
326         {
327                 out[0] = in[0] * r;
328                 out[1] = in[1] * g;
329                 out[2] = in[2] * b;
330                 out[3] = in[3];
331                 in += 4;
332                 out += 4;
333         }
334 }
335
336 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
337 {
338         int i;
339         for (i = 0;i < verts;i++)
340         {
341                 out[0] = r;
342                 out[1] = g;
343                 out[2] = b;
344                 out[3] = a;
345                 out += 4;
346         }
347 }
348
349 // FIXME: move this to client?
350 void FOG_clear(void)
351 {
352         if (gamemode == GAME_NEHAHRA)
353         {
354                 Cvar_Set("gl_fogenable", "0");
355                 Cvar_Set("gl_fogdensity", "0.2");
356                 Cvar_Set("gl_fogred", "0.3");
357                 Cvar_Set("gl_foggreen", "0.3");
358                 Cvar_Set("gl_fogblue", "0.3");
359         }
360         r_refdef.fog_density = 0;
361         r_refdef.fog_red = 0;
362         r_refdef.fog_green = 0;
363         r_refdef.fog_blue = 0;
364         r_refdef.fog_alpha = 1;
365         r_refdef.fog_start = 0;
366         r_refdef.fog_end = 16384;
367         r_refdef.fog_height = 1<<30;
368         r_refdef.fog_fadedepth = 128;
369         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
370 }
371
372 static void R_BuildBlankTextures(void)
373 {
374         unsigned char data[4];
375         data[2] = 128; // normal X
376         data[1] = 128; // normal Y
377         data[0] = 255; // normal Z
378         data[3] = 128; // height
379         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 255;
381         data[1] = 255;
382         data[2] = 255;
383         data[3] = 255;
384         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385         data[0] = 128;
386         data[1] = 128;
387         data[2] = 128;
388         data[3] = 255;
389         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390         data[0] = 0;
391         data[1] = 0;
392         data[2] = 0;
393         data[3] = 255;
394         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
395 }
396
397 static void R_BuildNoTexture(void)
398 {
399         int x, y;
400         unsigned char pix[16][16][4];
401         // this makes a light grey/dark grey checkerboard texture
402         for (y = 0;y < 16;y++)
403         {
404                 for (x = 0;x < 16;x++)
405                 {
406                         if ((y < 8) ^ (x < 8))
407                         {
408                                 pix[y][x][0] = 128;
409                                 pix[y][x][1] = 128;
410                                 pix[y][x][2] = 128;
411                                 pix[y][x][3] = 255;
412                         }
413                         else
414                         {
415                                 pix[y][x][0] = 64;
416                                 pix[y][x][1] = 64;
417                                 pix[y][x][2] = 64;
418                                 pix[y][x][3] = 255;
419                         }
420                 }
421         }
422         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
423 }
424
425 static void R_BuildWhiteCube(void)
426 {
427         unsigned char data[6*1*1*4];
428         memset(data, 255, sizeof(data));
429         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
430 }
431
432 static void R_BuildNormalizationCube(void)
433 {
434         int x, y, side;
435         vec3_t v;
436         vec_t s, t, intensity;
437 #define NORMSIZE 64
438         unsigned char *data;
439         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
440         for (side = 0;side < 6;side++)
441         {
442                 for (y = 0;y < NORMSIZE;y++)
443                 {
444                         for (x = 0;x < NORMSIZE;x++)
445                         {
446                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
447                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
448                                 switch(side)
449                                 {
450                                 default:
451                                 case 0:
452                                         v[0] = 1;
453                                         v[1] = -t;
454                                         v[2] = -s;
455                                         break;
456                                 case 1:
457                                         v[0] = -1;
458                                         v[1] = -t;
459                                         v[2] = s;
460                                         break;
461                                 case 2:
462                                         v[0] = s;
463                                         v[1] = 1;
464                                         v[2] = t;
465                                         break;
466                                 case 3:
467                                         v[0] = s;
468                                         v[1] = -1;
469                                         v[2] = -t;
470                                         break;
471                                 case 4:
472                                         v[0] = s;
473                                         v[1] = -t;
474                                         v[2] = 1;
475                                         break;
476                                 case 5:
477                                         v[0] = -s;
478                                         v[1] = -t;
479                                         v[2] = -1;
480                                         break;
481                                 }
482                                 intensity = 127.0f / sqrt(DotProduct(v, v));
483                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
484                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
485                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
486                                 data[((side*64+y)*64+x)*4+3] = 255;
487                         }
488                 }
489         }
490         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
491         Mem_Free(data);
492 }
493
494 static void R_BuildFogTexture(void)
495 {
496         int x, b;
497 #define FOGWIDTH 256
498         unsigned char data1[FOGWIDTH][4];
499         //unsigned char data2[FOGWIDTH][4];
500         double d, r, alpha;
501
502         r_refdef.fogmasktable_start = r_refdef.fog_start;
503         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
504         r_refdef.fogmasktable_range = r_refdef.fogrange;
505         r_refdef.fogmasktable_density = r_refdef.fog_density;
506
507         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
508         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
509         {
510                 d = (x * r - r_refdef.fogmasktable_start);
511                 if(developer_extra.integer)
512                         Con_DPrintf("%f ", d);
513                 d = max(0, d);
514                 if (r_fog_exp2.integer)
515                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
516                 else
517                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
518                 if(developer_extra.integer)
519                         Con_DPrintf(" : %f ", alpha);
520                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
521                 if(developer_extra.integer)
522                         Con_DPrintf(" = %f\n", alpha);
523                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
524         }
525
526         for (x = 0;x < FOGWIDTH;x++)
527         {
528                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
529                 data1[x][0] = b;
530                 data1[x][1] = b;
531                 data1[x][2] = b;
532                 data1[x][3] = 255;
533                 //data2[x][0] = 255 - b;
534                 //data2[x][1] = 255 - b;
535                 //data2[x][2] = 255 - b;
536                 //data2[x][3] = 255;
537         }
538         if (r_texture_fogattenuation)
539         {
540                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
542         }
543         else
544         {
545                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
546                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
547         }
548 }
549
550 static void R_BuildFogHeightTexture(void)
551 {
552         unsigned char *inpixels;
553         int size;
554         int x;
555         int y;
556         int j;
557         float c[4];
558         float f;
559         inpixels = NULL;
560         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
561         if (r_refdef.fogheighttexturename[0])
562                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
563         if (!inpixels)
564         {
565                 r_refdef.fog_height_tablesize = 0;
566                 if (r_texture_fogheighttexture)
567                         R_FreeTexture(r_texture_fogheighttexture);
568                 r_texture_fogheighttexture = NULL;
569                 if (r_refdef.fog_height_table2d)
570                         Mem_Free(r_refdef.fog_height_table2d);
571                 r_refdef.fog_height_table2d = NULL;
572                 if (r_refdef.fog_height_table1d)
573                         Mem_Free(r_refdef.fog_height_table1d);
574                 r_refdef.fog_height_table1d = NULL;
575                 return;
576         }
577         size = image_width;
578         r_refdef.fog_height_tablesize = size;
579         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
580         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
581         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
582         Mem_Free(inpixels);
583         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
584         // average fog color table accounting for every fog layer between a point
585         // and the camera.  (Note: attenuation is handled separately!)
586         for (y = 0;y < size;y++)
587         {
588                 for (x = 0;x < size;x++)
589                 {
590                         Vector4Clear(c);
591                         f = 0;
592                         if (x < y)
593                         {
594                                 for (j = x;j <= y;j++)
595                                 {
596                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
597                                         f++;
598                                 }
599                         }
600                         else
601                         {
602                                 for (j = x;j >= y;j--)
603                                 {
604                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605                                         f++;
606                                 }
607                         }
608                         f = 1.0f / f;
609                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
610                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
611                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
612                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
613                 }
614         }
615         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
616 }
617
618 //=======================================================================================================================================================
619
620 static const char *builtinshaderstring =
621 #include "shader_glsl.h"
622 ;
623
624 const char *builtinhlslshaderstring =
625 #include "shader_hlsl.h"
626 ;
627
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
630
631 //=======================================================================================================================================================
632
633 typedef struct shaderpermutationinfo_s
634 {
635         const char *pretext;
636         const char *name;
637 }
638 shaderpermutationinfo_t;
639
640 typedef struct shadermodeinfo_s
641 {
642         const char *vertexfilename;
643         const char *geometryfilename;
644         const char *fragmentfilename;
645         const char *pretext;
646         const char *name;
647 }
648 shadermodeinfo_t;
649
650 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
651 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
652 {
653         {"#define USEDIFFUSE\n", " diffuse"},
654         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
655         {"#define USEVIEWTINT\n", " viewtint"},
656         {"#define USECOLORMAPPING\n", " colormapping"},
657         {"#define USESATURATION\n", " saturation"},
658         {"#define USEFOGINSIDE\n", " foginside"},
659         {"#define USEFOGOUTSIDE\n", " fogoutside"},
660         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
661         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
662         {"#define USEGAMMARAMPS\n", " gammaramps"},
663         {"#define USECUBEFILTER\n", " cubefilter"},
664         {"#define USEGLOW\n", " glow"},
665         {"#define USEBLOOM\n", " bloom"},
666         {"#define USESPECULAR\n", " specular"},
667         {"#define USEPOSTPROCESSING\n", " postprocessing"},
668         {"#define USEREFLECTION\n", " reflection"},
669         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
670         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
671         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
672         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
673         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
674         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
675         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
676         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
677         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
678         {"#define USEALPHAKILL\n", " alphakill"},
679         {"#define USEREFLECTCUBE\n", " reflectcube"},
680         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
681         {"#define USEBOUNCEGRID\n", " bouncegrid"},
682         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
683 };
684
685 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
686 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
687 {
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 };
705
706 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
707 {
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
724 };
725
726 struct r_glsl_permutation_s;
727 typedef struct r_glsl_permutation_s
728 {
729         /// hash lookup data
730         struct r_glsl_permutation_s *hashnext;
731         unsigned int mode;
732         unsigned int permutation;
733
734         /// indicates if we have tried compiling this permutation already
735         qboolean compiled;
736         /// 0 if compilation failed
737         int program;
738         // texture units assigned to each detected uniform
739         int tex_Texture_First;
740         int tex_Texture_Second;
741         int tex_Texture_GammaRamps;
742         int tex_Texture_Normal;
743         int tex_Texture_Color;
744         int tex_Texture_Gloss;
745         int tex_Texture_Glow;
746         int tex_Texture_SecondaryNormal;
747         int tex_Texture_SecondaryColor;
748         int tex_Texture_SecondaryGloss;
749         int tex_Texture_SecondaryGlow;
750         int tex_Texture_Pants;
751         int tex_Texture_Shirt;
752         int tex_Texture_FogHeightTexture;
753         int tex_Texture_FogMask;
754         int tex_Texture_Lightmap;
755         int tex_Texture_Deluxemap;
756         int tex_Texture_Attenuation;
757         int tex_Texture_Cube;
758         int tex_Texture_Refraction;
759         int tex_Texture_Reflection;
760         int tex_Texture_ShadowMap2D;
761         int tex_Texture_CubeProjection;
762         int tex_Texture_ScreenDepth;
763         int tex_Texture_ScreenNormalMap;
764         int tex_Texture_ScreenDiffuse;
765         int tex_Texture_ScreenSpecular;
766         int tex_Texture_ReflectMask;
767         int tex_Texture_ReflectCube;
768         int tex_Texture_BounceGrid;
769         /// locations of detected uniforms in program object, or -1 if not found
770         int loc_Texture_First;
771         int loc_Texture_Second;
772         int loc_Texture_GammaRamps;
773         int loc_Texture_Normal;
774         int loc_Texture_Color;
775         int loc_Texture_Gloss;
776         int loc_Texture_Glow;
777         int loc_Texture_SecondaryNormal;
778         int loc_Texture_SecondaryColor;
779         int loc_Texture_SecondaryGloss;
780         int loc_Texture_SecondaryGlow;
781         int loc_Texture_Pants;
782         int loc_Texture_Shirt;
783         int loc_Texture_FogHeightTexture;
784         int loc_Texture_FogMask;
785         int loc_Texture_Lightmap;
786         int loc_Texture_Deluxemap;
787         int loc_Texture_Attenuation;
788         int loc_Texture_Cube;
789         int loc_Texture_Refraction;
790         int loc_Texture_Reflection;
791         int loc_Texture_ShadowMap2D;
792         int loc_Texture_CubeProjection;
793         int loc_Texture_ScreenDepth;
794         int loc_Texture_ScreenNormalMap;
795         int loc_Texture_ScreenDiffuse;
796         int loc_Texture_ScreenSpecular;
797         int loc_Texture_ReflectMask;
798         int loc_Texture_ReflectCube;
799         int loc_Texture_BounceGrid;
800         int loc_Alpha;
801         int loc_BloomBlur_Parameters;
802         int loc_ClientTime;
803         int loc_Color_Ambient;
804         int loc_Color_Diffuse;
805         int loc_Color_Specular;
806         int loc_Color_Glow;
807         int loc_Color_Pants;
808         int loc_Color_Shirt;
809         int loc_DeferredColor_Ambient;
810         int loc_DeferredColor_Diffuse;
811         int loc_DeferredColor_Specular;
812         int loc_DeferredMod_Diffuse;
813         int loc_DeferredMod_Specular;
814         int loc_DistortScaleRefractReflect;
815         int loc_EyePosition;
816         int loc_FogColor;
817         int loc_FogHeightFade;
818         int loc_FogPlane;
819         int loc_FogPlaneViewDist;
820         int loc_FogRangeRecip;
821         int loc_LightColor;
822         int loc_LightDir;
823         int loc_LightPosition;
824         int loc_OffsetMapping_ScaleSteps;
825         int loc_PixelSize;
826         int loc_ReflectColor;
827         int loc_ReflectFactor;
828         int loc_ReflectOffset;
829         int loc_RefractColor;
830         int loc_Saturation;
831         int loc_ScreenCenterRefractReflect;
832         int loc_ScreenScaleRefractReflect;
833         int loc_ScreenToDepth;
834         int loc_ShadowMap_Parameters;
835         int loc_ShadowMap_TextureScale;
836         int loc_SpecularPower;
837         int loc_UserVec1;
838         int loc_UserVec2;
839         int loc_UserVec3;
840         int loc_UserVec4;
841         int loc_ViewTintColor;
842         int loc_ViewToLight;
843         int loc_ModelToLight;
844         int loc_TexMatrix;
845         int loc_BackgroundTexMatrix;
846         int loc_ModelViewProjectionMatrix;
847         int loc_ModelViewMatrix;
848         int loc_PixelToScreenTexCoord;
849         int loc_ModelToReflectCube;
850         int loc_ShadowMapMatrix;
851         int loc_BloomColorSubtract;
852         int loc_NormalmapScrollBlend;
853         int loc_BounceGridMatrix;
854         int loc_BounceGridIntensity;
855 }
856 r_glsl_permutation_t;
857
858 #define SHADERPERMUTATION_HASHSIZE 256
859
860
861 // non-degradable "lightweight" shader parameters to keep the permutations simpler
862 // these can NOT degrade! only use for simple stuff
863 enum
864 {
865         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
866         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
867         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
868         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
869         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
870         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
871         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
872 };
873 #define SHADERSTATICPARMS_COUNT 7
874
875 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
876 static int shaderstaticparms_count = 0;
877
878 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
879 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
880 qboolean R_CompileShader_CheckStaticParms(void)
881 {
882         static int r_compileshader_staticparms_save[1];
883         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
884         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
885
886         // detect all
887         if (r_glsl_saturation_redcompensate.integer)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
889         if (r_glsl_vertextextureblend_usebothalphas.integer)
890                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
891         if (r_shadow_glossexact.integer)
892                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
893         if (r_glsl_postprocess.integer)
894         {
895                 if (r_glsl_postprocess_uservec1_enable.integer)
896                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
897                 if (r_glsl_postprocess_uservec2_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
899                 if (r_glsl_postprocess_uservec3_enable.integer)
900                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
901                 if (r_glsl_postprocess_uservec4_enable.integer)
902                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
903         }
904         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
905 }
906
907 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
908         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
909                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
910         else \
911                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
912 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
913 {
914         shaderstaticparms_count = 0;
915
916         // emit all
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
924 }
925
926 /// information about each possible shader permutation
927 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
928 /// currently selected permutation
929 r_glsl_permutation_t *r_glsl_permutation;
930 /// storage for permutations linked in the hash table
931 memexpandablearray_t r_glsl_permutationarray;
932
933 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
934 {
935         //unsigned int hashdepth = 0;
936         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
937         r_glsl_permutation_t *p;
938         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
939         {
940                 if (p->mode == mode && p->permutation == permutation)
941                 {
942                         //if (hashdepth > 10)
943                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
944                         return p;
945                 }
946                 //hashdepth++;
947         }
948         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
949         p->mode = mode;
950         p->permutation = permutation;
951         p->hashnext = r_glsl_permutationhash[mode][hashindex];
952         r_glsl_permutationhash[mode][hashindex] = p;
953         //if (hashdepth > 10)
954         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
955         return p;
956 }
957
958 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
959 {
960         char *shaderstring;
961         if (!filename || !filename[0])
962                 return NULL;
963         if (!strcmp(filename, "glsl/default.glsl"))
964         {
965                 if (!glslshaderstring)
966                 {
967                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
968                         if (glslshaderstring)
969                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
970                         else
971                                 glslshaderstring = (char *)builtinshaderstring;
972                 }
973                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
974                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
975                 return shaderstring;
976         }
977         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
978         if (shaderstring)
979         {
980                 if (printfromdisknotice)
981                         Con_DPrintf("from disk %s... ", filename);
982                 return shaderstring;
983         }
984         return shaderstring;
985 }
986
987 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
988 {
989         int i;
990         int sampler;
991         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
992         char *vertexstring, *geometrystring, *fragmentstring;
993         char permutationname[256];
994         int vertstrings_count = 0;
995         int geomstrings_count = 0;
996         int fragstrings_count = 0;
997         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
998         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
999         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1000
1001         if (p->compiled)
1002                 return;
1003         p->compiled = true;
1004         p->program = 0;
1005
1006         permutationname[0] = 0;
1007         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1008         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1009         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1010
1011         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1012
1013         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1014         if(vid.support.gl20shaders130)
1015         {
1016                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1017                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1018                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1019                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1020                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1021                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1022         }
1023
1024         // the first pretext is which type of shader to compile as
1025         // (later these will all be bound together as a program object)
1026         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1027         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1028         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1029
1030         // the second pretext is the mode (for example a light source)
1031         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1032         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1033         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1034         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1035
1036         // now add all the permutation pretexts
1037         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1038         {
1039                 if (permutation & (1<<i))
1040                 {
1041                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1042                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1043                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1044                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1045                 }
1046                 else
1047                 {
1048                         // keep line numbers correct
1049                         vertstrings_list[vertstrings_count++] = "\n";
1050                         geomstrings_list[geomstrings_count++] = "\n";
1051                         fragstrings_list[fragstrings_count++] = "\n";
1052                 }
1053         }
1054
1055         // add static parms
1056         R_CompileShader_AddStaticParms(mode, permutation);
1057         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058         vertstrings_count += shaderstaticparms_count;
1059         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1060         geomstrings_count += shaderstaticparms_count;
1061         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1062         fragstrings_count += shaderstaticparms_count;
1063
1064         // now append the shader text itself
1065         vertstrings_list[vertstrings_count++] = vertexstring;
1066         geomstrings_list[geomstrings_count++] = geometrystring;
1067         fragstrings_list[fragstrings_count++] = fragmentstring;
1068
1069         // if any sources were NULL, clear the respective list
1070         if (!vertexstring)
1071                 vertstrings_count = 0;
1072         if (!geometrystring)
1073                 geomstrings_count = 0;
1074         if (!fragmentstring)
1075                 fragstrings_count = 0;
1076
1077         // compile the shader program
1078         if (vertstrings_count + geomstrings_count + fragstrings_count)
1079                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1080         if (p->program)
1081         {
1082                 CHECKGLERROR
1083                 qglUseProgram(p->program);CHECKGLERROR
1084                 // look up all the uniform variable names we care about, so we don't
1085                 // have to look them up every time we set them
1086
1087                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1088                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1089                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1090                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1091                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1092                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1093                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1094                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1095                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1096                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1097                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1098                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1099                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1100                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1101                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1102                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1103                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1104                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1105                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1106                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1107                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1108                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1109                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1110                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1111                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1112                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1113                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1114                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1115                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1116                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1117                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1118                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1119                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1120                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1121                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1122                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1123                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1124                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1125                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1126                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1127                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1128                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1129                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1130                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1131                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1132                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1133                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1134                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1135                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1136                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1137                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1138                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1139                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1140                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1141                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1142                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1143                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1144                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1145                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1146                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1147                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1148                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1149                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1150                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1151                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1152                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1153                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1154                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1155                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1156                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1157                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1158                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1159                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1160                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1161                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1162                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1163                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1164                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1165                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1166                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1167                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1168                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1169                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1170                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1171                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1172                 // initialize the samplers to refer to the texture units we use
1173                 p->tex_Texture_First = -1;
1174                 p->tex_Texture_Second = -1;
1175                 p->tex_Texture_GammaRamps = -1;
1176                 p->tex_Texture_Normal = -1;
1177                 p->tex_Texture_Color = -1;
1178                 p->tex_Texture_Gloss = -1;
1179                 p->tex_Texture_Glow = -1;
1180                 p->tex_Texture_SecondaryNormal = -1;
1181                 p->tex_Texture_SecondaryColor = -1;
1182                 p->tex_Texture_SecondaryGloss = -1;
1183                 p->tex_Texture_SecondaryGlow = -1;
1184                 p->tex_Texture_Pants = -1;
1185                 p->tex_Texture_Shirt = -1;
1186                 p->tex_Texture_FogHeightTexture = -1;
1187                 p->tex_Texture_FogMask = -1;
1188                 p->tex_Texture_Lightmap = -1;
1189                 p->tex_Texture_Deluxemap = -1;
1190                 p->tex_Texture_Attenuation = -1;
1191                 p->tex_Texture_Cube = -1;
1192                 p->tex_Texture_Refraction = -1;
1193                 p->tex_Texture_Reflection = -1;
1194                 p->tex_Texture_ShadowMap2D = -1;
1195                 p->tex_Texture_CubeProjection = -1;
1196                 p->tex_Texture_ScreenDepth = -1;
1197                 p->tex_Texture_ScreenNormalMap = -1;
1198                 p->tex_Texture_ScreenDiffuse = -1;
1199                 p->tex_Texture_ScreenSpecular = -1;
1200                 p->tex_Texture_ReflectMask = -1;
1201                 p->tex_Texture_ReflectCube = -1;
1202                 p->tex_Texture_BounceGrid = -1;
1203                 sampler = 0;
1204                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1205                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1206                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1207                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1208                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1209                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1210                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1211                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1212                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1213                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1214                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1215                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1216                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1217                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1218                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1219                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1220                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1221                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1222                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1223                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1224                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1225                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1226                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1227                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1228                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1229                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1230                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1231                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1232                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1233                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1234                 CHECKGLERROR
1235                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1236         }
1237         else
1238                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1239
1240         // free the strings
1241         if (vertexstring)
1242                 Mem_Free(vertexstring);
1243         if (geometrystring)
1244                 Mem_Free(geometrystring);
1245         if (fragmentstring)
1246                 Mem_Free(fragmentstring);
1247 }
1248
1249 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1250 {
1251         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1252         if (r_glsl_permutation != perm)
1253         {
1254                 r_glsl_permutation = perm;
1255                 if (!r_glsl_permutation->program)
1256                 {
1257                         if (!r_glsl_permutation->compiled)
1258                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1259                         if (!r_glsl_permutation->program)
1260                         {
1261                                 // remove features until we find a valid permutation
1262                                 int i;
1263                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1264                                 {
1265                                         // reduce i more quickly whenever it would not remove any bits
1266                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1267                                         if (!(permutation & j))
1268                                                 continue;
1269                                         permutation -= j;
1270                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1271                                         if (!r_glsl_permutation->compiled)
1272                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1273                                         if (r_glsl_permutation->program)
1274                                                 break;
1275                                 }
1276                                 if (i >= SHADERPERMUTATION_COUNT)
1277                                 {
1278                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1279                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1280                                         qglUseProgram(0);CHECKGLERROR
1281                                         return; // no bit left to clear, entire mode is broken
1282                                 }
1283                         }
1284                 }
1285                 CHECKGLERROR
1286                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1287         }
1288         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1289         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1290         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1291 }
1292
1293 #ifdef SUPPORTD3D
1294
1295 #ifdef SUPPORTD3D
1296 #include <d3d9.h>
1297 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1298 extern D3DCAPS9 vid_d3d9caps;
1299 #endif
1300
1301 struct r_hlsl_permutation_s;
1302 typedef struct r_hlsl_permutation_s
1303 {
1304         /// hash lookup data
1305         struct r_hlsl_permutation_s *hashnext;
1306         unsigned int mode;
1307         unsigned int permutation;
1308
1309         /// indicates if we have tried compiling this permutation already
1310         qboolean compiled;
1311         /// NULL if compilation failed
1312         IDirect3DVertexShader9 *vertexshader;
1313         IDirect3DPixelShader9 *pixelshader;
1314 }
1315 r_hlsl_permutation_t;
1316
1317 typedef enum D3DVSREGISTER_e
1318 {
1319         D3DVSREGISTER_TexMatrix = 0, // float4x4
1320         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1321         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1322         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1323         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1324         D3DVSREGISTER_ModelToLight = 20, // float4x4
1325         D3DVSREGISTER_EyePosition = 24,
1326         D3DVSREGISTER_FogPlane = 25,
1327         D3DVSREGISTER_LightDir = 26,
1328         D3DVSREGISTER_LightPosition = 27,
1329 }
1330 D3DVSREGISTER_t;
1331
1332 typedef enum D3DPSREGISTER_e
1333 {
1334         D3DPSREGISTER_Alpha = 0,
1335         D3DPSREGISTER_BloomBlur_Parameters = 1,
1336         D3DPSREGISTER_ClientTime = 2,
1337         D3DPSREGISTER_Color_Ambient = 3,
1338         D3DPSREGISTER_Color_Diffuse = 4,
1339         D3DPSREGISTER_Color_Specular = 5,
1340         D3DPSREGISTER_Color_Glow = 6,
1341         D3DPSREGISTER_Color_Pants = 7,
1342         D3DPSREGISTER_Color_Shirt = 8,
1343         D3DPSREGISTER_DeferredColor_Ambient = 9,
1344         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1345         D3DPSREGISTER_DeferredColor_Specular = 11,
1346         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1347         D3DPSREGISTER_DeferredMod_Specular = 13,
1348         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1349         D3DPSREGISTER_EyePosition = 15, // unused
1350         D3DPSREGISTER_FogColor = 16,
1351         D3DPSREGISTER_FogHeightFade = 17,
1352         D3DPSREGISTER_FogPlane = 18,
1353         D3DPSREGISTER_FogPlaneViewDist = 19,
1354         D3DPSREGISTER_FogRangeRecip = 20,
1355         D3DPSREGISTER_LightColor = 21,
1356         D3DPSREGISTER_LightDir = 22, // unused
1357         D3DPSREGISTER_LightPosition = 23,
1358         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1359         D3DPSREGISTER_PixelSize = 25,
1360         D3DPSREGISTER_ReflectColor = 26,
1361         D3DPSREGISTER_ReflectFactor = 27,
1362         D3DPSREGISTER_ReflectOffset = 28,
1363         D3DPSREGISTER_RefractColor = 29,
1364         D3DPSREGISTER_Saturation = 30,
1365         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1366         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1367         D3DPSREGISTER_ScreenToDepth = 33,
1368         D3DPSREGISTER_ShadowMap_Parameters = 34,
1369         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1370         D3DPSREGISTER_SpecularPower = 36,
1371         D3DPSREGISTER_UserVec1 = 37,
1372         D3DPSREGISTER_UserVec2 = 38,
1373         D3DPSREGISTER_UserVec3 = 39,
1374         D3DPSREGISTER_UserVec4 = 40,
1375         D3DPSREGISTER_ViewTintColor = 41,
1376         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1377         D3DPSREGISTER_BloomColorSubtract = 43,
1378         D3DPSREGISTER_ViewToLight = 44, // float4x4
1379         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1380         D3DPSREGISTER_NormalmapScrollBlend = 52,
1381         // next at 53
1382 }
1383 D3DPSREGISTER_t;
1384
1385 /// information about each possible shader permutation
1386 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1387 /// currently selected permutation
1388 r_hlsl_permutation_t *r_hlsl_permutation;
1389 /// storage for permutations linked in the hash table
1390 memexpandablearray_t r_hlsl_permutationarray;
1391
1392 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1393 {
1394         //unsigned int hashdepth = 0;
1395         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1396         r_hlsl_permutation_t *p;
1397         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1398         {
1399                 if (p->mode == mode && p->permutation == permutation)
1400                 {
1401                         //if (hashdepth > 10)
1402                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1403                         return p;
1404                 }
1405                 //hashdepth++;
1406         }
1407         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1408         p->mode = mode;
1409         p->permutation = permutation;
1410         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1411         r_hlsl_permutationhash[mode][hashindex] = p;
1412         //if (hashdepth > 10)
1413         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1414         return p;
1415 }
1416
1417 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1418 {
1419         char *shaderstring;
1420         if (!filename || !filename[0])
1421                 return NULL;
1422         if (!strcmp(filename, "hlsl/default.hlsl"))
1423         {
1424                 if (!hlslshaderstring)
1425                 {
1426                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1427                         if (hlslshaderstring)
1428                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1429                         else
1430                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1431                 }
1432                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1433                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1434                 return shaderstring;
1435         }
1436         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1437         if (shaderstring)
1438         {
1439                 if (printfromdisknotice)
1440                         Con_DPrintf("from disk %s... ", filename);
1441                 return shaderstring;
1442         }
1443         return shaderstring;
1444 }
1445
1446 #include <d3dx9.h>
1447 //#include <d3dx9shader.h>
1448 //#include <d3dx9mesh.h>
1449
1450 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1451 {
1452         DWORD *vsbin = NULL;
1453         DWORD *psbin = NULL;
1454         fs_offset_t vsbinsize;
1455         fs_offset_t psbinsize;
1456 //      IDirect3DVertexShader9 *vs = NULL;
1457 //      IDirect3DPixelShader9 *ps = NULL;
1458         ID3DXBuffer *vslog = NULL;
1459         ID3DXBuffer *vsbuffer = NULL;
1460         ID3DXConstantTable *vsconstanttable = NULL;
1461         ID3DXBuffer *pslog = NULL;
1462         ID3DXBuffer *psbuffer = NULL;
1463         ID3DXConstantTable *psconstanttable = NULL;
1464         int vsresult = 0;
1465         int psresult = 0;
1466         char temp[MAX_INPUTLINE];
1467         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1468         qboolean debugshader = gl_paranoid.integer != 0;
1469         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1470         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1471         if (!debugshader)
1472         {
1473                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1474                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1475         }
1476         if ((!vsbin && vertstring) || (!psbin && fragstring))
1477         {
1478                 const char* dllnames_d3dx9 [] =
1479                 {
1480                         "d3dx9_43.dll",
1481                         "d3dx9_42.dll",
1482                         "d3dx9_41.dll",
1483                         "d3dx9_40.dll",
1484                         "d3dx9_39.dll",
1485                         "d3dx9_38.dll",
1486                         "d3dx9_37.dll",
1487                         "d3dx9_36.dll",
1488                         "d3dx9_35.dll",
1489                         "d3dx9_34.dll",
1490                         "d3dx9_33.dll",
1491                         "d3dx9_32.dll",
1492                         "d3dx9_31.dll",
1493                         "d3dx9_30.dll",
1494                         "d3dx9_29.dll",
1495                         "d3dx9_28.dll",
1496                         "d3dx9_27.dll",
1497                         "d3dx9_26.dll",
1498                         "d3dx9_25.dll",
1499                         "d3dx9_24.dll",
1500                         NULL
1501                 };
1502                 dllhandle_t d3dx9_dll = NULL;
1503                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1504                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1505                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1506                 dllfunction_t d3dx9_dllfuncs[] =
1507                 {
1508                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1509                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1510                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1511                         {NULL, NULL}
1512                 };
1513                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1514                 {
1515                         DWORD shaderflags = 0;
1516                         if (debugshader)
1517                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1518                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1519                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1520                         if (vertstring && vertstring[0])
1521                         {
1522                                 if (debugshader)
1523                                 {
1524 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1525 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1526                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1527                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1528                                 }
1529                                 else
1530                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1531                                 if (vsbuffer)
1532                                 {
1533                                         vsbinsize = vsbuffer->GetBufferSize();
1534                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1535                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1536                                         vsbuffer->Release();
1537                                 }
1538                                 if (vslog)
1539                                 {
1540                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1541                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1542                                         vslog->Release();
1543                                 }
1544                         }
1545                         if (fragstring && fragstring[0])
1546                         {
1547                                 if (debugshader)
1548                                 {
1549 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1550 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1551                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1552                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1553                                 }
1554                                 else
1555                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1556                                 if (psbuffer)
1557                                 {
1558                                         psbinsize = psbuffer->GetBufferSize();
1559                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1560                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1561                                         psbuffer->Release();
1562                                 }
1563                                 if (pslog)
1564                                 {
1565                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1566                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1567                                         pslog->Release();
1568                                 }
1569                         }
1570                         Sys_UnloadLibrary(&d3dx9_dll);
1571                 }
1572                 else
1573                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1574         }
1575         if (vsbin && psbin)
1576         {
1577                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1578                 if (FAILED(vsresult))
1579                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1580                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1581                 if (FAILED(psresult))
1582                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1583         }
1584         // free the shader data
1585         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1586         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1587 }
1588
1589 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1590 {
1591         int i;
1592         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1593         int vertstring_length = 0;
1594         int geomstring_length = 0;
1595         int fragstring_length = 0;
1596         char *t;
1597         char *vertexstring, *geometrystring, *fragmentstring;
1598         char *vertstring, *geomstring, *fragstring;
1599         char permutationname[256];
1600         char cachename[256];
1601         int vertstrings_count = 0;
1602         int geomstrings_count = 0;
1603         int fragstrings_count = 0;
1604         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1605         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1606         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1607
1608         if (p->compiled)
1609                 return;
1610         p->compiled = true;
1611         p->vertexshader = NULL;
1612         p->pixelshader = NULL;
1613
1614         permutationname[0] = 0;
1615         cachename[0] = 0;
1616         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1617         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1618         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1619
1620         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1621         strlcat(cachename, "hlsl/", sizeof(cachename));
1622
1623         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1624         vertstrings_count = 0;
1625         geomstrings_count = 0;
1626         fragstrings_count = 0;
1627         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1628         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1629         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1630
1631         // the first pretext is which type of shader to compile as
1632         // (later these will all be bound together as a program object)
1633         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1634         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1635         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1636
1637         // the second pretext is the mode (for example a light source)
1638         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1639         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1640         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1641         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1642         strlcat(cachename, modeinfo->name, sizeof(cachename));
1643
1644         // now add all the permutation pretexts
1645         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1646         {
1647                 if (permutation & (1<<i))
1648                 {
1649                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1650                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1651                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1652                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1653                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1654                 }
1655                 else
1656                 {
1657                         // keep line numbers correct
1658                         vertstrings_list[vertstrings_count++] = "\n";
1659                         geomstrings_list[geomstrings_count++] = "\n";
1660                         fragstrings_list[fragstrings_count++] = "\n";
1661                 }
1662         }
1663
1664         // add static parms
1665         R_CompileShader_AddStaticParms(mode, permutation);
1666         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667         vertstrings_count += shaderstaticparms_count;
1668         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1669         geomstrings_count += shaderstaticparms_count;
1670         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1671         fragstrings_count += shaderstaticparms_count;
1672
1673         // replace spaces in the cachename with _ characters
1674         for (i = 0;cachename[i];i++)
1675                 if (cachename[i] == ' ')
1676                         cachename[i] = '_';
1677
1678         // now append the shader text itself
1679         vertstrings_list[vertstrings_count++] = vertexstring;
1680         geomstrings_list[geomstrings_count++] = geometrystring;
1681         fragstrings_list[fragstrings_count++] = fragmentstring;
1682
1683         // if any sources were NULL, clear the respective list
1684         if (!vertexstring)
1685                 vertstrings_count = 0;
1686         if (!geometrystring)
1687                 geomstrings_count = 0;
1688         if (!fragmentstring)
1689                 fragstrings_count = 0;
1690
1691         vertstring_length = 0;
1692         for (i = 0;i < vertstrings_count;i++)
1693                 vertstring_length += strlen(vertstrings_list[i]);
1694         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1695         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1696                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1697
1698         geomstring_length = 0;
1699         for (i = 0;i < geomstrings_count;i++)
1700                 geomstring_length += strlen(geomstrings_list[i]);
1701         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1702         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1703                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1704
1705         fragstring_length = 0;
1706         for (i = 0;i < fragstrings_count;i++)
1707                 fragstring_length += strlen(fragstrings_list[i]);
1708         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1709         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1710                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1711
1712         // try to load the cached shader, or generate one
1713         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1714
1715         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1716                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1717         else
1718                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1719
1720         // free the strings
1721         if (vertstring)
1722                 Mem_Free(vertstring);
1723         if (geomstring)
1724                 Mem_Free(geomstring);
1725         if (fragstring)
1726                 Mem_Free(fragstring);
1727         if (vertexstring)
1728                 Mem_Free(vertexstring);
1729         if (geometrystring)
1730                 Mem_Free(geometrystring);
1731         if (fragmentstring)
1732                 Mem_Free(fragmentstring);
1733 }
1734
1735 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1736 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1737 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1738 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1739 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1740 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1741
1742 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1743 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1744 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1745 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1746 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1747 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1748
1749 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1750 {
1751         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1752         if (r_hlsl_permutation != perm)
1753         {
1754                 r_hlsl_permutation = perm;
1755                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1756                 {
1757                         if (!r_hlsl_permutation->compiled)
1758                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1759                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1760                         {
1761                                 // remove features until we find a valid permutation
1762                                 int i;
1763                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1764                                 {
1765                                         // reduce i more quickly whenever it would not remove any bits
1766                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1767                                         if (!(permutation & j))
1768                                                 continue;
1769                                         permutation -= j;
1770                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1771                                         if (!r_hlsl_permutation->compiled)
1772                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1773                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1774                                                 break;
1775                                 }
1776                                 if (i >= SHADERPERMUTATION_COUNT)
1777                                 {
1778                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1779                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1780                                         return; // no bit left to clear, entire mode is broken
1781                                 }
1782                         }
1783                 }
1784                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1785                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1786         }
1787         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1788         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1789         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1790 }
1791 #endif
1792
1793 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1794 {
1795         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1796         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1797         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1798         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1799 }
1800
1801 void R_GLSL_Restart_f(void)
1802 {
1803         unsigned int i, limit;
1804         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1805                 Mem_Free(glslshaderstring);
1806         glslshaderstring = NULL;
1807         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1808                 Mem_Free(hlslshaderstring);
1809         hlslshaderstring = NULL;
1810         switch(vid.renderpath)
1811         {
1812         case RENDERPATH_D3D9:
1813 #ifdef SUPPORTD3D
1814                 {
1815                         r_hlsl_permutation_t *p;
1816                         r_hlsl_permutation = NULL;
1817                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1818                         for (i = 0;i < limit;i++)
1819                         {
1820                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1821                                 {
1822                                         if (p->vertexshader)
1823                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1824                                         if (p->pixelshader)
1825                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1826                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1827                                 }
1828                         }
1829                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1830                 }
1831 #endif
1832                 break;
1833         case RENDERPATH_D3D10:
1834                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1835                 break;
1836         case RENDERPATH_D3D11:
1837                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1838                 break;
1839         case RENDERPATH_GL20:
1840         case RENDERPATH_GLES2:
1841                 {
1842                         r_glsl_permutation_t *p;
1843                         r_glsl_permutation = NULL;
1844                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1845                         for (i = 0;i < limit;i++)
1846                         {
1847                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1848                                 {
1849                                         GL_Backend_FreeProgram(p->program);
1850                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1851                                 }
1852                         }
1853                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1854                 }
1855                 break;
1856         case RENDERPATH_GL13:
1857         case RENDERPATH_GL11:
1858                 break;
1859         case RENDERPATH_SOFT:
1860                 break;
1861         }
1862 }
1863
1864 void R_GLSL_DumpShader_f(void)
1865 {
1866         int i;
1867         qfile_t *file;
1868
1869         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1870         if (file)
1871         {
1872                 FS_Print(file, "/* The engine may define the following macros:\n");
1873                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1874                 for (i = 0;i < SHADERMODE_COUNT;i++)
1875                         FS_Print(file, glslshadermodeinfo[i].pretext);
1876                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1877                         FS_Print(file, shaderpermutationinfo[i].pretext);
1878                 FS_Print(file, "*/\n");
1879                 FS_Print(file, builtinshaderstring);
1880                 FS_Close(file);
1881                 Con_Printf("glsl/default.glsl written\n");
1882         }
1883         else
1884                 Con_Printf("failed to write to glsl/default.glsl\n");
1885
1886         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1887         if (file)
1888         {
1889                 FS_Print(file, "/* The engine may define the following macros:\n");
1890                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1891                 for (i = 0;i < SHADERMODE_COUNT;i++)
1892                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1893                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1894                         FS_Print(file, shaderpermutationinfo[i].pretext);
1895                 FS_Print(file, "*/\n");
1896                 FS_Print(file, builtinhlslshaderstring);
1897                 FS_Close(file);
1898                 Con_Printf("hlsl/default.hlsl written\n");
1899         }
1900         else
1901                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1902 }
1903
1904 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1905 {
1906         if (!second)
1907                 texturemode = GL_MODULATE;
1908         switch (vid.renderpath)
1909         {
1910         case RENDERPATH_D3D9:
1911 #ifdef SUPPORTD3D
1912                 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))));
1913                 R_Mesh_TexBind(GL20TU_FIRST , first );
1914                 R_Mesh_TexBind(GL20TU_SECOND, second);
1915 #endif
1916                 break;
1917         case RENDERPATH_D3D10:
1918                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1919                 break;
1920         case RENDERPATH_D3D11:
1921                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1922                 break;
1923         case RENDERPATH_GL20:
1924         case RENDERPATH_GLES2:
1925                 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))));
1926                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1927                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1928                 break;
1929         case RENDERPATH_GL13:
1930                 R_Mesh_TexBind(0, first );
1931                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1932                 R_Mesh_TexBind(1, second);
1933                 if (second)
1934                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1935                 break;
1936         case RENDERPATH_GL11:
1937                 R_Mesh_TexBind(0, first );
1938                 break;
1939         case RENDERPATH_SOFT:
1940                 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))));
1941                 R_Mesh_TexBind(GL20TU_FIRST , first );
1942                 R_Mesh_TexBind(GL20TU_SECOND, second);
1943                 break;
1944         }
1945 }
1946
1947 void R_SetupShader_DepthOrShadow(void)
1948 {
1949         switch (vid.renderpath)
1950         {
1951         case RENDERPATH_D3D9:
1952 #ifdef SUPPORTD3D
1953                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1954 #endif
1955                 break;
1956         case RENDERPATH_D3D10:
1957                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958                 break;
1959         case RENDERPATH_D3D11:
1960                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961                 break;
1962         case RENDERPATH_GL20:
1963         case RENDERPATH_GLES2:
1964                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1965                 break;
1966         case RENDERPATH_GL13:
1967                 R_Mesh_TexBind(0, 0);
1968                 R_Mesh_TexBind(1, 0);
1969                 break;
1970         case RENDERPATH_GL11:
1971                 R_Mesh_TexBind(0, 0);
1972                 break;
1973         case RENDERPATH_SOFT:
1974                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1975                 break;
1976         }
1977 }
1978
1979 void R_SetupShader_ShowDepth(void)
1980 {
1981         switch (vid.renderpath)
1982         {
1983         case RENDERPATH_D3D9:
1984 #ifdef SUPPORTHLSL
1985                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1986 #endif
1987                 break;
1988         case RENDERPATH_D3D10:
1989                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1990                 break;
1991         case RENDERPATH_D3D11:
1992                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1993                 break;
1994         case RENDERPATH_GL20:
1995         case RENDERPATH_GLES2:
1996                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1997                 break;
1998         case RENDERPATH_GL13:
1999                 break;
2000         case RENDERPATH_GL11:
2001                 break;
2002         case RENDERPATH_SOFT:
2003                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2004                 break;
2005         }
2006 }
2007
2008 extern qboolean r_shadow_usingdeferredprepass;
2009 extern cvar_t r_shadow_deferred_8bitrange;
2010 extern rtexture_t *r_shadow_attenuationgradienttexture;
2011 extern rtexture_t *r_shadow_attenuation2dtexture;
2012 extern rtexture_t *r_shadow_attenuation3dtexture;
2013 extern qboolean r_shadow_usingshadowmap2d;
2014 extern qboolean r_shadow_usingshadowmaportho;
2015 extern float r_shadow_shadowmap_texturescale[2];
2016 extern float r_shadow_shadowmap_parameters[4];
2017 extern qboolean r_shadow_shadowmapvsdct;
2018 extern qboolean r_shadow_shadowmapsampler;
2019 extern int r_shadow_shadowmappcf;
2020 extern rtexture_t *r_shadow_shadowmap2dtexture;
2021 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2022 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2023 extern matrix4x4_t r_shadow_shadowmapmatrix;
2024 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2025 extern int r_shadow_prepass_width;
2026 extern int r_shadow_prepass_height;
2027 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2028 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2029 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2030 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2031 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2032
2033 #define BLENDFUNC_ALLOWS_COLORMOD      1
2034 #define BLENDFUNC_ALLOWS_FOG           2
2035 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2036 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2037 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2038 static int R_BlendFuncFlags(int src, int dst)
2039 {
2040         int r = 0;
2041
2042         // a blendfunc allows colormod if:
2043         // a) it can never keep the destination pixel invariant, or
2044         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2045         // this is to prevent unintended side effects from colormod
2046
2047         // a blendfunc allows fog if:
2048         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2049         // this is to prevent unintended side effects from fog
2050
2051         // these checks are the output of fogeval.pl
2052
2053         r |= BLENDFUNC_ALLOWS_COLORMOD;
2054         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2055         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2056         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2057         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2058         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2059         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2063         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2064         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2065         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2066         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2067         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2068         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2069         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2070         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2071         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2072         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2073         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2074         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2075
2076         return r;
2077 }
2078
2079 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)
2080 {
2081         // select a permutation of the lighting shader appropriate to this
2082         // combination of texture, entity, light source, and fogging, only use the
2083         // minimum features necessary to avoid wasting rendering time in the
2084         // fragment shader on features that are not being used
2085         unsigned int permutation = 0;
2086         unsigned int mode = 0;
2087         int blendfuncflags;
2088         static float dummy_colormod[3] = {1, 1, 1};
2089         float *colormod = rsurface.colormod;
2090         float m16f[16];
2091         matrix4x4_t tempmatrix;
2092         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2093         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2094                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2095         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2096                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2097         if (rsurfacepass == RSURFPASS_BACKGROUND)
2098         {
2099                 // distorted background
2100                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2101                 {
2102                         mode = SHADERMODE_WATER;
2103                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2104                         {
2105                                 // this is the right thing to do for wateralpha
2106                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2107                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2108                         }
2109                         else
2110                         {
2111                                 // this is the right thing to do for entity alpha
2112                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2113                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2114                         }
2115                 }
2116                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2117                 {
2118                         mode = SHADERMODE_REFRACTION;
2119                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2120                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2121                 }
2122                 else
2123                 {
2124                         mode = SHADERMODE_GENERIC;
2125                         permutation |= SHADERPERMUTATION_DIFFUSE;
2126                         GL_BlendFunc(GL_ONE, GL_ZERO);
2127                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2128                 }
2129         }
2130         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2131         {
2132                 if (r_glsl_offsetmapping.integer)
2133                 {
2134                         switch(rsurface.texture->offsetmapping)
2135                         {
2136                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2137                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2138                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2139                         case OFFSETMAPPING_OFF: break;
2140                         }
2141                 }
2142                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2143                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2144                 // normalmap (deferred prepass), may use alpha test on diffuse
2145                 mode = SHADERMODE_DEFERREDGEOMETRY;
2146                 GL_BlendFunc(GL_ONE, GL_ZERO);
2147                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2148         }
2149         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2150         {
2151                 if (r_glsl_offsetmapping.integer)
2152                 {
2153                         switch(rsurface.texture->offsetmapping)
2154                         {
2155                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2156                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2157                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2158                         case OFFSETMAPPING_OFF: break;
2159                         }
2160                 }
2161                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2162                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2163                 // light source
2164                 mode = SHADERMODE_LIGHTSOURCE;
2165                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2166                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2167                 if (diffusescale > 0)
2168                         permutation |= SHADERPERMUTATION_DIFFUSE;
2169                 if (specularscale > 0)
2170                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2171                 if (r_refdef.fogenabled)
2172                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2173                 if (rsurface.texture->colormapping)
2174                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2175                 if (r_shadow_usingshadowmap2d)
2176                 {
2177                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2178                         if(r_shadow_shadowmapvsdct)
2179                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2180
2181                         if (r_shadow_shadowmapsampler)
2182                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2183                         if (r_shadow_shadowmappcf > 1)
2184                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2185                         else if (r_shadow_shadowmappcf)
2186                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2187                 }
2188                 if (rsurface.texture->reflectmasktexture)
2189                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2190                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2191                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2192         }
2193         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2194         {
2195                 if (r_glsl_offsetmapping.integer)
2196                 {
2197                         switch(rsurface.texture->offsetmapping)
2198                         {
2199                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2200                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202                         case OFFSETMAPPING_OFF: break;
2203                         }
2204                 }
2205                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2206                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2207                 // unshaded geometry (fullbright or ambient model lighting)
2208                 mode = SHADERMODE_FLATCOLOR;
2209                 ambientscale = diffusescale = specularscale = 0;
2210                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2211                         permutation |= SHADERPERMUTATION_GLOW;
2212                 if (r_refdef.fogenabled)
2213                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2214                 if (rsurface.texture->colormapping)
2215                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2216                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2217                 {
2218                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2219                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2220
2221                         if (r_shadow_shadowmapsampler)
2222                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2223                         if (r_shadow_shadowmappcf > 1)
2224                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2225                         else if (r_shadow_shadowmappcf)
2226                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2227                 }
2228                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2229                         permutation |= SHADERPERMUTATION_REFLECTION;
2230                 if (rsurface.texture->reflectmasktexture)
2231                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2232                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2233                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2234         }
2235         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2236         {
2237                 if (r_glsl_offsetmapping.integer)
2238                 {
2239                         switch(rsurface.texture->offsetmapping)
2240                         {
2241                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2242                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2243                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2244                         case OFFSETMAPPING_OFF: break;
2245                         }
2246                 }
2247                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2248                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2249                 // directional model lighting
2250                 mode = SHADERMODE_LIGHTDIRECTION;
2251                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2252                         permutation |= SHADERPERMUTATION_GLOW;
2253                 permutation |= SHADERPERMUTATION_DIFFUSE;
2254                 if (specularscale > 0)
2255                         permutation |= SHADERPERMUTATION_SPECULAR;
2256                 if (r_refdef.fogenabled)
2257                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2258                 if (rsurface.texture->colormapping)
2259                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2260                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2261                 {
2262                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2263                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2264
2265                         if (r_shadow_shadowmapsampler)
2266                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2267                         if (r_shadow_shadowmappcf > 1)
2268                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2269                         else if (r_shadow_shadowmappcf)
2270                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2271                 }
2272                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2273                         permutation |= SHADERPERMUTATION_REFLECTION;
2274                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2275                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2276                 if (rsurface.texture->reflectmasktexture)
2277                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2278                 if (r_shadow_bouncegridtexture)
2279                 {
2280                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2281                         if (r_shadow_bouncegriddirectional)
2282                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2283                 }
2284                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2285                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2286         }
2287         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2288         {
2289                 if (r_glsl_offsetmapping.integer)
2290                 {
2291                         switch(rsurface.texture->offsetmapping)
2292                         {
2293                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2294                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2295                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2296                         case OFFSETMAPPING_OFF: break;
2297                         }
2298                 }
2299                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2300                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2301                 // ambient model lighting
2302                 mode = SHADERMODE_LIGHTDIRECTION;
2303                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2304                         permutation |= SHADERPERMUTATION_GLOW;
2305                 if (r_refdef.fogenabled)
2306                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2307                 if (rsurface.texture->colormapping)
2308                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2309                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2310                 {
2311                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2312                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2313
2314                         if (r_shadow_shadowmapsampler)
2315                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2316                         if (r_shadow_shadowmappcf > 1)
2317                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2318                         else if (r_shadow_shadowmappcf)
2319                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2320                 }
2321                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2322                         permutation |= SHADERPERMUTATION_REFLECTION;
2323                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2324                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2325                 if (rsurface.texture->reflectmasktexture)
2326                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2327                 if (r_shadow_bouncegridtexture)
2328                 {
2329                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2330                         if (r_shadow_bouncegriddirectional)
2331                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2332                 }
2333                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2334                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2335         }
2336         else
2337         {
2338                 if (r_glsl_offsetmapping.integer)
2339                 {
2340                         switch(rsurface.texture->offsetmapping)
2341                         {
2342                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2343                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2344                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2345                         case OFFSETMAPPING_OFF: break;
2346                         }
2347                 }
2348                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2349                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2350                 // lightmapped wall
2351                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2352                         permutation |= SHADERPERMUTATION_GLOW;
2353                 if (r_refdef.fogenabled)
2354                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2355                 if (rsurface.texture->colormapping)
2356                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2357                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2358                 {
2359                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2360                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2361
2362                         if (r_shadow_shadowmapsampler)
2363                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2364                         if (r_shadow_shadowmappcf > 1)
2365                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2366                         else if (r_shadow_shadowmappcf)
2367                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2368                 }
2369                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2370                         permutation |= SHADERPERMUTATION_REFLECTION;
2371                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2372                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2373                 if (rsurface.texture->reflectmasktexture)
2374                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2375                 if (FAKELIGHT_ENABLED)
2376                 {
2377                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2378                         mode = SHADERMODE_FAKELIGHT;
2379                         permutation |= SHADERPERMUTATION_DIFFUSE;
2380                         if (specularscale > 0)
2381                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2382                 }
2383                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2384                 {
2385                         // deluxemapping (light direction texture)
2386                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2387                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2388                         else
2389                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2390                         permutation |= SHADERPERMUTATION_DIFFUSE;
2391                         if (specularscale > 0)
2392                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2393                 }
2394                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2395                 {
2396                         // fake deluxemapping (uniform light direction in tangentspace)
2397                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2398                         permutation |= SHADERPERMUTATION_DIFFUSE;
2399                         if (specularscale > 0)
2400                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2401                 }
2402                 else if (rsurface.uselightmaptexture)
2403                 {
2404                         // ordinary lightmapping (q1bsp, q3bsp)
2405                         mode = SHADERMODE_LIGHTMAP;
2406                 }
2407                 else
2408                 {
2409                         // ordinary vertex coloring (q3bsp)
2410                         mode = SHADERMODE_VERTEXCOLOR;
2411                 }
2412                 if (r_shadow_bouncegridtexture)
2413                 {
2414                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2415                         if (r_shadow_bouncegriddirectional)
2416                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2417                 }
2418                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2419                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2420         }
2421         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2422                 colormod = dummy_colormod;
2423         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2424                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2425         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2426                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2427         switch(vid.renderpath)
2428         {
2429         case RENDERPATH_D3D9:
2430 #ifdef SUPPORTD3D
2431                 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);
2432                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2433                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2434                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2435                 if (mode == SHADERMODE_LIGHTSOURCE)
2436                 {
2437                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2438                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2439                 }
2440                 else
2441                 {
2442                         if (mode == SHADERMODE_LIGHTDIRECTION)
2443                         {
2444                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2445                         }
2446                 }
2447                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2448                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2449                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2450                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2451                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2452
2453                 if (mode == SHADERMODE_LIGHTSOURCE)
2454                 {
2455                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2456                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2457                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2458                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2459                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2460
2461                         // additive passes are only darkened by fog, not tinted
2462                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2463                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2464                 }
2465                 else
2466                 {
2467                         if (mode == SHADERMODE_FLATCOLOR)
2468                         {
2469                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2470                         }
2471                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2472                         {
2473                                 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]);
2474                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2475                                 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);
2476                                 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);
2477                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2478                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2479                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2480                         }
2481                         else
2482                         {
2483                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2484                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2485                                 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);
2486                                 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);
2487                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2488                         }
2489                         // additive passes are only darkened by fog, not tinted
2490                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2491                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2492                         else
2493                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2494                         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);
2495                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2496                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2497                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2498                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2499                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2500                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2501                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2502                         if (mode == SHADERMODE_WATER)
2503                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2504                 }
2505                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2506                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2507                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2508                 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));
2509                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2510                 if (rsurface.texture->pantstexture)
2511                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2512                 else
2513                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2514                 if (rsurface.texture->shirttexture)
2515                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2516                 else
2517                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2518                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2519                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2520                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2521                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2522                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2523                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2524                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2525                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2526                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2527                         );
2528                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2529                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2530
2531                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2532                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2533                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2534                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2535                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2536                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2537                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2538                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2539                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2540                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2541                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2542                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2543                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2544                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2545                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2546                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2547                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2548                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2549                 {
2550                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2551                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2552                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2553                 }
2554                 else
2555                 {
2556                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2557                 }
2558 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2559 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2560                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2561                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2562                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2563                 {
2564                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2565                         if (rsurface.rtlight)
2566                         {
2567                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2568                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2569                         }
2570                 }
2571 #endif
2572                 break;
2573         case RENDERPATH_D3D10:
2574                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2575                 break;
2576         case RENDERPATH_D3D11:
2577                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2578                 break;
2579         case RENDERPATH_GL20:
2580         case RENDERPATH_GLES2:
2581                 if (!vid.useinterleavedarrays)
2582                 {
2583                         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);
2584                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2585                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2586                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2587                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2588                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2589                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2590                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2591                 }
2592                 else
2593                 {
2594                         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);
2595                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2596                 }
2597                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2598                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2599                 if (mode == SHADERMODE_LIGHTSOURCE)
2600                 {
2601                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2602                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2603                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2604                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2605                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2606                         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);
2607         
2608                         // additive passes are only darkened by fog, not tinted
2609                         if (r_glsl_permutation->loc_FogColor >= 0)
2610                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2611                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2612                 }
2613                 else
2614                 {
2615                         if (mode == SHADERMODE_FLATCOLOR)
2616                         {
2617                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2618                         }
2619                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2620                         {
2621                                 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]);
2622                                 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]);
2623                                 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);
2624                                 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);
2625                                 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);
2626                                 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]);
2627                                 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]);
2628                         }
2629                         else
2630                         {
2631                                 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]);
2632                                 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]);
2633                                 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);
2634                                 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);
2635                                 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);
2636                         }
2637                         // additive passes are only darkened by fog, not tinted
2638                         if (r_glsl_permutation->loc_FogColor >= 0)
2639                         {
2640                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2641                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2642                                 else
2643                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2644                         }
2645                         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);
2646                         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]);
2647                         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]);
2648                         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]);
2649                         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]);
2650                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2651                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2652                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2653                         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]);
2654                 }
2655                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2656                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2657                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2658                 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]);
2659                 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]);
2660
2661                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2662                 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));
2663                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2664                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2665                 {
2666                         if (rsurface.texture->pantstexture)
2667                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2668                         else
2669                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2670                 }
2671                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2672                 {
2673                         if (rsurface.texture->shirttexture)
2674                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2675                         else
2676                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2677                 }
2678                 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]);
2679                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2680                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2681                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2682                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2683                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2684                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2685                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2686                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2687                         );
2688                 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]);
2689                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2690                 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);}
2691                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2692
2693                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2694                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2695                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2696                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2697                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2698                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2699                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2700                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2701                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2702                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2703                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2704                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2705                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2706                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2707                 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);
2708                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2709                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2710                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2711                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2712                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2713                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2714                 {
2715                         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);
2716                         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);
2717                         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);
2718                 }
2719                 else
2720                 {
2721                         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);
2722                 }
2723                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2724                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2725                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2726                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2727                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2728                 {
2729                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2730                         if (rsurface.rtlight)
2731                         {
2732                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2733                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2734                         }
2735                 }
2736                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2737                 CHECKGLERROR
2738                 break;
2739         case RENDERPATH_GL13:
2740         case RENDERPATH_GL11:
2741                 break;
2742         case RENDERPATH_SOFT:
2743                 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);
2744                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2745                 R_SetupShader_SetPermutationSoft(mode, permutation);
2746                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2747                 if (mode == SHADERMODE_LIGHTSOURCE)
2748                 {
2749                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2750                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2751                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2752                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2753                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2754                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2755         
2756                         // additive passes are only darkened by fog, not tinted
2757                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2758                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2759                 }
2760                 else
2761                 {
2762                         if (mode == SHADERMODE_FLATCOLOR)
2763                         {
2764                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2765                         }
2766                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2767                         {
2768                                 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]);
2769                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2770                                 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);
2771                                 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);
2772                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2773                                 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]);
2774                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2775                         }
2776                         else
2777                         {
2778                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2779                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2780                                 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);
2781                                 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);
2782                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2783                         }
2784                         // additive passes are only darkened by fog, not tinted
2785                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2786                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2787                         else
2788                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2789                         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);
2790                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2791                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2792                         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]);
2793                         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]);
2794                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2795                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2796                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2797                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2798                 }
2799                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2800                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2801                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2802                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2803                 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]);
2804
2805                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2806                 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));
2807                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2808                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2809                 {
2810                         if (rsurface.texture->pantstexture)
2811                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2812                         else
2813                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2814                 }
2815                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2816                 {
2817                         if (rsurface.texture->shirttexture)
2818                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2819                         else
2820                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2821                 }
2822                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2823                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2824                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2825                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2826                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2827                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2828                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2829                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2830                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2831                         );
2832                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2833                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2834
2835                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2836                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2837                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2838                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2839                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2840                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2841                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2842                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2843                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2844                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2845                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2846                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2847                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2848                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2849                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2850                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2851                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2852                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2853                 {
2854                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2855                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2856                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2857                 }
2858                 else
2859                 {
2860                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2861                 }
2862 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2863 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2864                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2865                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2866                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2867                 {
2868                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2869                         if (rsurface.rtlight)
2870                         {
2871                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2872                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2873                         }
2874                 }
2875                 break;
2876         }
2877 }
2878
2879 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2880 {
2881         // select a permutation of the lighting shader appropriate to this
2882         // combination of texture, entity, light source, and fogging, only use the
2883         // minimum features necessary to avoid wasting rendering time in the
2884         // fragment shader on features that are not being used
2885         unsigned int permutation = 0;
2886         unsigned int mode = 0;
2887         const float *lightcolorbase = rtlight->currentcolor;
2888         float ambientscale = rtlight->ambientscale;
2889         float diffusescale = rtlight->diffusescale;
2890         float specularscale = rtlight->specularscale;
2891         // this is the location of the light in view space
2892         vec3_t viewlightorigin;
2893         // this transforms from view space (camera) to light space (cubemap)
2894         matrix4x4_t viewtolight;
2895         matrix4x4_t lighttoview;
2896         float viewtolight16f[16];
2897         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2898         // light source
2899         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2900         if (rtlight->currentcubemap != r_texture_whitecube)
2901                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2902         if (diffusescale > 0)
2903                 permutation |= SHADERPERMUTATION_DIFFUSE;
2904         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2905                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2906         if (r_shadow_usingshadowmap2d)
2907         {
2908                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2909                 if (r_shadow_shadowmapvsdct)
2910                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2911
2912                 if (r_shadow_shadowmapsampler)
2913                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2914                 if (r_shadow_shadowmappcf > 1)
2915                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2916                 else if (r_shadow_shadowmappcf)
2917                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2918         }
2919         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2920         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2921         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2922         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2923         switch(vid.renderpath)
2924         {
2925         case RENDERPATH_D3D9:
2926 #ifdef SUPPORTD3D
2927                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2928                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2929                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2930                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2931                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2932                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2933                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2934                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2935                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2936                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2937                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2938
2939                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2940                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2941                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2942                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2943                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2944                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2945 #endif
2946                 break;
2947         case RENDERPATH_D3D10:
2948                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2949                 break;
2950         case RENDERPATH_D3D11:
2951                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2952                 break;
2953         case RENDERPATH_GL20:
2954         case RENDERPATH_GLES2:
2955                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2956                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2957                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2958                 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);
2959                 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);
2960                 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);
2961                 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]);
2962                 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]);
2963                 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));
2964                 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]);
2965                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2966
2967                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2968                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2969                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2970                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2971                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2972                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2973                 break;
2974         case RENDERPATH_GL13:
2975         case RENDERPATH_GL11:
2976                 break;
2977         case RENDERPATH_SOFT:
2978                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2979                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2980                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2981                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2982                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2983                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2984                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2985                 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]);
2986                 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));
2987                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2988                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2989
2990                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2991                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2992                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2993                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2994                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2995                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2996                 break;
2997         }
2998 }
2999
3000 #define SKINFRAME_HASH 1024
3001
3002 typedef struct
3003 {
3004         int loadsequence; // incremented each level change
3005         memexpandablearray_t array;
3006         skinframe_t *hash[SKINFRAME_HASH];
3007 }
3008 r_skinframe_t;
3009 r_skinframe_t r_skinframe;
3010
3011 void R_SkinFrame_PrepareForPurge(void)
3012 {
3013         r_skinframe.loadsequence++;
3014         // wrap it without hitting zero
3015         if (r_skinframe.loadsequence >= 200)
3016                 r_skinframe.loadsequence = 1;
3017 }
3018
3019 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3020 {
3021         if (!skinframe)
3022                 return;
3023         // mark the skinframe as used for the purging code
3024         skinframe->loadsequence = r_skinframe.loadsequence;
3025 }
3026
3027 void R_SkinFrame_Purge(void)
3028 {
3029         int i;
3030         skinframe_t *s;
3031         for (i = 0;i < SKINFRAME_HASH;i++)
3032         {
3033                 for (s = r_skinframe.hash[i];s;s = s->next)
3034                 {
3035                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3036                         {
3037                                 if (s->merged == s->base)
3038                                         s->merged = NULL;
3039                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3040                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3041                                 R_PurgeTexture(s->merged);s->merged = NULL;
3042                                 R_PurgeTexture(s->base  );s->base   = NULL;
3043                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3044                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3045                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3046                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3047                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3048                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3049                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3050                                 s->loadsequence = 0;
3051                         }
3052                 }
3053         }
3054 }
3055
3056 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3057         skinframe_t *item;
3058         char basename[MAX_QPATH];
3059
3060         Image_StripImageExtension(name, basename, sizeof(basename));
3061
3062         if( last == NULL ) {
3063                 int hashindex;
3064                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3065                 item = r_skinframe.hash[hashindex];
3066         } else {
3067                 item = last->next;
3068         }
3069
3070         // linearly search through the hash bucket
3071         for( ; item ; item = item->next ) {
3072                 if( !strcmp( item->basename, basename ) ) {
3073                         return item;
3074                 }
3075         }
3076         return NULL;
3077 }
3078
3079 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3080 {
3081         skinframe_t *item;
3082         int hashindex;
3083         char basename[MAX_QPATH];
3084
3085         Image_StripImageExtension(name, basename, sizeof(basename));
3086
3087         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3088         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3089                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3090                         break;
3091
3092         if (!item) {
3093                 rtexture_t *dyntexture;
3094                 // check whether its a dynamic texture
3095                 dyntexture = CL_GetDynTexture( basename );
3096                 if (!add && !dyntexture)
3097                         return NULL;
3098                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3099                 memset(item, 0, sizeof(*item));
3100                 strlcpy(item->basename, basename, sizeof(item->basename));
3101                 item->base = dyntexture; // either NULL or dyntexture handle
3102                 item->textureflags = textureflags;
3103                 item->comparewidth = comparewidth;
3104                 item->compareheight = compareheight;
3105                 item->comparecrc = comparecrc;
3106                 item->next = r_skinframe.hash[hashindex];
3107                 r_skinframe.hash[hashindex] = item;
3108         }
3109         else if( item->base == NULL )
3110         {
3111                 rtexture_t *dyntexture;
3112                 // check whether its a dynamic texture
3113                 // 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]
3114                 dyntexture = CL_GetDynTexture( basename );
3115                 item->base = dyntexture; // either NULL or dyntexture handle
3116         }
3117
3118         R_SkinFrame_MarkUsed(item);
3119         return item;
3120 }
3121
3122 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3123         { \
3124                 unsigned long long avgcolor[5], wsum; \
3125                 int pix, comp, w; \
3126                 avgcolor[0] = 0; \
3127                 avgcolor[1] = 0; \
3128                 avgcolor[2] = 0; \
3129                 avgcolor[3] = 0; \
3130                 avgcolor[4] = 0; \
3131                 wsum = 0; \
3132                 for(pix = 0; pix < cnt; ++pix) \
3133                 { \
3134                         w = 0; \
3135                         for(comp = 0; comp < 3; ++comp) \
3136                                 w += getpixel; \
3137                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3138                         { \
3139                                 ++wsum; \
3140                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3141                                 w = getpixel; \
3142                                 for(comp = 0; comp < 3; ++comp) \
3143                                         avgcolor[comp] += getpixel * w; \
3144                                 avgcolor[3] += w; \
3145                         } \
3146                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3147                         avgcolor[4] += getpixel; \
3148                 } \
3149                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3150                         avgcolor[3] = 1; \
3151                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3152                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3153                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3154                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3155         }
3156
3157 extern cvar_t gl_picmip;
3158 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3159 {
3160         int j;
3161         unsigned char *pixels;
3162         unsigned char *bumppixels;
3163         unsigned char *basepixels = NULL;
3164         int basepixels_width = 0;
3165         int basepixels_height = 0;
3166         skinframe_t *skinframe;
3167         rtexture_t *ddsbase = NULL;
3168         qboolean ddshasalpha = false;
3169         float ddsavgcolor[4];
3170         char basename[MAX_QPATH];
3171         int miplevel = R_PicmipForFlags(textureflags);
3172         int savemiplevel = miplevel;
3173         int mymiplevel;
3174
3175         if (cls.state == ca_dedicated)
3176                 return NULL;
3177
3178         // return an existing skinframe if already loaded
3179         // if loading of the first image fails, don't make a new skinframe as it
3180         // would cause all future lookups of this to be missing
3181         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3182         if (skinframe && skinframe->base)
3183                 return skinframe;
3184
3185         Image_StripImageExtension(name, basename, sizeof(basename));
3186
3187         // check for DDS texture file first
3188         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3189         {
3190                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3191                 if (basepixels == NULL)
3192                         return NULL;
3193         }
3194
3195         // FIXME handle miplevel
3196
3197         if (developer_loading.integer)
3198                 Con_Printf("loading skin \"%s\"\n", name);
3199
3200         // we've got some pixels to store, so really allocate this new texture now
3201         if (!skinframe)
3202                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3203         skinframe->stain = NULL;
3204         skinframe->merged = NULL;
3205         skinframe->base = NULL;
3206         skinframe->pants = NULL;
3207         skinframe->shirt = NULL;
3208         skinframe->nmap = NULL;
3209         skinframe->gloss = NULL;
3210         skinframe->glow = NULL;
3211         skinframe->fog = NULL;
3212         skinframe->reflect = NULL;
3213         skinframe->hasalpha = false;
3214
3215         if (ddsbase)
3216         {
3217                 skinframe->base = ddsbase;
3218                 skinframe->hasalpha = ddshasalpha;
3219                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3220                 if (r_loadfog && skinframe->hasalpha)
3221                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3222                 //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]);
3223         }
3224         else
3225         {
3226                 basepixels_width = image_width;
3227                 basepixels_height = image_height;
3228                 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);
3229                 if (textureflags & TEXF_ALPHA)
3230                 {
3231                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3232                         {
3233                                 if (basepixels[j] < 255)
3234                                 {
3235                                         skinframe->hasalpha = true;
3236                                         break;
3237                                 }
3238                         }
3239                         if (r_loadfog && skinframe->hasalpha)
3240                         {
3241                                 // has transparent pixels
3242                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3243                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3244                                 {
3245                                         pixels[j+0] = 255;
3246                                         pixels[j+1] = 255;
3247                                         pixels[j+2] = 255;
3248                                         pixels[j+3] = basepixels[j+3];
3249                                 }
3250                                 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);
3251                                 Mem_Free(pixels);
3252                         }
3253                 }
3254                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3255                 //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]);
3256                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3257                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3258                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3259                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3260         }
3261
3262         if (r_loaddds)
3263         {
3264                 mymiplevel = savemiplevel;
3265                 if (r_loadnormalmap)
3266                         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);
3267                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3268                 if (r_loadgloss)
3269                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3270                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3271                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3272                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3273         }
3274
3275         // _norm is the name used by tenebrae and has been adopted as standard
3276         if (r_loadnormalmap && skinframe->nmap == NULL)
3277         {
3278                 mymiplevel = savemiplevel;
3279                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3280                 {
3281                         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);
3282                         Mem_Free(pixels);
3283                         pixels = NULL;
3284                 }
3285                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3286                 {
3287                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3288                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3289                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3290                         Mem_Free(pixels);
3291                         Mem_Free(bumppixels);
3292                 }
3293                 else if (r_shadow_bumpscale_basetexture.value > 0)
3294                 {
3295                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3296                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3297                         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);
3298                         Mem_Free(pixels);
3299                 }
3300                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3301                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3302         }
3303
3304         // _luma is supported only for tenebrae compatibility
3305         // _glow is the preferred name
3306         mymiplevel = savemiplevel;
3307         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))))
3308         {
3309                 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);
3310                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3311                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3312                 Mem_Free(pixels);pixels = NULL;
3313         }
3314
3315         mymiplevel = savemiplevel;
3316         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3317         {
3318                 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);
3319                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3320                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3321                 Mem_Free(pixels);
3322                 pixels = NULL;
3323         }
3324
3325         mymiplevel = savemiplevel;
3326         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3327         {
3328                 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);
3329                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3330                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3331                 Mem_Free(pixels);
3332                 pixels = NULL;
3333         }
3334
3335         mymiplevel = savemiplevel;
3336         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3337         {
3338                 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);
3339                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3340                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3341                 Mem_Free(pixels);
3342                 pixels = NULL;
3343         }
3344
3345         mymiplevel = savemiplevel;
3346         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3347         {
3348                 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);
3349                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3350                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3351                 Mem_Free(pixels);
3352                 pixels = NULL;
3353         }
3354
3355         if (basepixels)
3356                 Mem_Free(basepixels);
3357
3358         return skinframe;
3359 }
3360
3361 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3362 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3363 {
3364         int i;
3365         unsigned char *temp1, *temp2;
3366         skinframe_t *skinframe;
3367
3368         if (cls.state == ca_dedicated)
3369                 return NULL;
3370
3371         // if already loaded just return it, otherwise make a new skinframe
3372         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3373         if (skinframe && skinframe->base)
3374                 return skinframe;
3375
3376         skinframe->stain = NULL;
3377         skinframe->merged = NULL;
3378         skinframe->base = NULL;
3379         skinframe->pants = NULL;
3380         skinframe->shirt = NULL;
3381         skinframe->nmap = NULL;
3382         skinframe->gloss = NULL;
3383         skinframe->glow = NULL;
3384         skinframe->fog = NULL;
3385         skinframe->reflect = NULL;
3386         skinframe->hasalpha = false;
3387
3388         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3389         if (!skindata)
3390                 return NULL;
3391
3392         if (developer_loading.integer)
3393                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3394
3395         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3396         {
3397                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3398                 temp2 = temp1 + width * height * 4;
3399                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3400                 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);
3401                 Mem_Free(temp1);
3402         }
3403         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3404         if (textureflags & TEXF_ALPHA)
3405         {
3406                 for (i = 3;i < width * height * 4;i += 4)
3407                 {
3408                         if (skindata[i] < 255)
3409                         {
3410                                 skinframe->hasalpha = true;
3411                                 break;
3412                         }
3413                 }
3414                 if (r_loadfog && skinframe->hasalpha)
3415                 {
3416                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3417                         memcpy(fogpixels, skindata, width * height * 4);
3418                         for (i = 0;i < width * height * 4;i += 4)
3419                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3420                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3421                         Mem_Free(fogpixels);
3422                 }
3423         }
3424
3425         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3426         //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]);
3427
3428         return skinframe;
3429 }
3430
3431 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3432 {
3433         int i;
3434         int featuresmask;
3435         skinframe_t *skinframe;
3436
3437         if (cls.state == ca_dedicated)
3438                 return NULL;
3439
3440         // if already loaded just return it, otherwise make a new skinframe
3441         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3442         if (skinframe && skinframe->base)
3443                 return skinframe;
3444
3445         skinframe->stain = NULL;
3446         skinframe->merged = NULL;
3447         skinframe->base = NULL;
3448         skinframe->pants = NULL;
3449         skinframe->shirt = NULL;
3450         skinframe->nmap = NULL;
3451         skinframe->gloss = NULL;
3452         skinframe->glow = NULL;
3453         skinframe->fog = NULL;
3454         skinframe->reflect = NULL;
3455         skinframe->hasalpha = false;
3456
3457         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3458         if (!skindata)
3459                 return NULL;
3460
3461         if (developer_loading.integer)
3462                 Con_Printf("loading quake skin \"%s\"\n", name);
3463
3464         // 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)
3465         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3466         memcpy(skinframe->qpixels, skindata, width*height);
3467         skinframe->qwidth = width;
3468         skinframe->qheight = height;
3469
3470         featuresmask = 0;
3471         for (i = 0;i < width * height;i++)
3472                 featuresmask |= palette_featureflags[skindata[i]];
3473
3474         skinframe->hasalpha = false;
3475         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3476         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3477         skinframe->qgeneratemerged = true;
3478         skinframe->qgeneratebase = skinframe->qhascolormapping;
3479         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3480
3481         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3482         //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]);
3483
3484         return skinframe;
3485 }
3486
3487 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3488 {
3489         int width;
3490         int height;
3491         unsigned char *skindata;
3492
3493         if (!skinframe->qpixels)
3494                 return;
3495
3496         if (!skinframe->qhascolormapping)
3497                 colormapped = false;
3498
3499         if (colormapped)
3500         {
3501                 if (!skinframe->qgeneratebase)
3502                         return;
3503         }
3504         else
3505         {
3506                 if (!skinframe->qgeneratemerged)
3507                         return;
3508         }
3509
3510         width = skinframe->qwidth;
3511         height = skinframe->qheight;
3512         skindata = skinframe->qpixels;
3513
3514         if (skinframe->qgeneratenmap)
3515         {
3516                 unsigned char *temp1, *temp2;
3517                 skinframe->qgeneratenmap = false;
3518                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3519                 temp2 = temp1 + width * height * 4;
3520                 // use either a custom palette or the quake palette
3521                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3522                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3523                 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);
3524                 Mem_Free(temp1);
3525         }
3526
3527         if (skinframe->qgenerateglow)
3528         {
3529                 skinframe->qgenerateglow = false;
3530                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3531         }
3532
3533         if (colormapped)
3534         {
3535                 skinframe->qgeneratebase = false;
3536                 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);
3537                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3538                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3539         }
3540         else
3541         {
3542                 skinframe->qgeneratemerged = false;
3543                 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);
3544         }
3545
3546         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3547         {
3548                 Mem_Free(skinframe->qpixels);
3549                 skinframe->qpixels = NULL;
3550         }
3551 }
3552
3553 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)
3554 {
3555         int i;
3556         skinframe_t *skinframe;
3557
3558         if (cls.state == ca_dedicated)
3559                 return NULL;
3560
3561         // if already loaded just return it, otherwise make a new skinframe
3562         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3563         if (skinframe && skinframe->base)
3564                 return skinframe;
3565
3566         skinframe->stain = NULL;
3567         skinframe->merged = NULL;
3568         skinframe->base = NULL;
3569         skinframe->pants = NULL;
3570         skinframe->shirt = NULL;
3571         skinframe->nmap = NULL;
3572         skinframe->gloss = NULL;
3573         skinframe->glow = NULL;
3574         skinframe->fog = NULL;
3575         skinframe->reflect = NULL;
3576         skinframe->hasalpha = false;
3577
3578         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3579         if (!skindata)
3580                 return NULL;
3581
3582         if (developer_loading.integer)
3583                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3584
3585         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3586         if (textureflags & TEXF_ALPHA)
3587         {
3588                 for (i = 0;i < width * height;i++)
3589                 {
3590                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3591                         {
3592                                 skinframe->hasalpha = true;
3593                                 break;
3594                         }
3595                 }
3596                 if (r_loadfog && skinframe->hasalpha)
3597                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3598         }
3599
3600         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3601         //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]);
3602
3603         return skinframe;
3604 }
3605
3606 skinframe_t *R_SkinFrame_LoadMissing(void)
3607 {
3608         skinframe_t *skinframe;
3609
3610         if (cls.state == ca_dedicated)
3611                 return NULL;
3612
3613         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3614         skinframe->stain = NULL;
3615         skinframe->merged = NULL;
3616         skinframe->base = NULL;
3617         skinframe->pants = NULL;
3618         skinframe->shirt = NULL;
3619         skinframe->nmap = NULL;
3620         skinframe->gloss = NULL;
3621         skinframe->glow = NULL;
3622         skinframe->fog = NULL;
3623         skinframe->reflect = NULL;
3624         skinframe->hasalpha = false;
3625
3626         skinframe->avgcolor[0] = rand() / RAND_MAX;
3627         skinframe->avgcolor[1] = rand() / RAND_MAX;
3628         skinframe->avgcolor[2] = rand() / RAND_MAX;
3629         skinframe->avgcolor[3] = 1;
3630
3631         return skinframe;
3632 }
3633
3634 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3635 typedef struct suffixinfo_s
3636 {
3637         const char *suffix;
3638         qboolean flipx, flipy, flipdiagonal;
3639 }
3640 suffixinfo_t;
3641 static suffixinfo_t suffix[3][6] =
3642 {
3643         {
3644                 {"px",   false, false, false},
3645                 {"nx",   false, false, false},
3646                 {"py",   false, false, false},
3647                 {"ny",   false, false, false},
3648                 {"pz",   false, false, false},
3649                 {"nz",   false, false, false}
3650         },
3651         {
3652                 {"posx", false, false, false},
3653                 {"negx", false, false, false},
3654                 {"posy", false, false, false},
3655                 {"negy", false, false, false},
3656                 {"posz", false, false, false},
3657                 {"negz", false, false, false}
3658         },
3659         {
3660                 {"rt",    true, false,  true},
3661                 {"lf",   false,  true,  true},
3662                 {"ft",    true,  true, false},
3663                 {"bk",   false, false, false},
3664                 {"up",    true, false,  true},
3665                 {"dn",    true, false,  true}
3666         }
3667 };
3668
3669 static int componentorder[4] = {0, 1, 2, 3};
3670
3671 rtexture_t *R_LoadCubemap(const char *basename)
3672 {
3673         int i, j, cubemapsize;
3674         unsigned char *cubemappixels, *image_buffer;
3675         rtexture_t *cubemaptexture;
3676         char name[256];
3677         // must start 0 so the first loadimagepixels has no requested width/height
3678         cubemapsize = 0;
3679         cubemappixels = NULL;
3680         cubemaptexture = NULL;
3681         // keep trying different suffix groups (posx, px, rt) until one loads
3682         for (j = 0;j < 3 && !cubemappixels;j++)
3683         {
3684                 // load the 6 images in the suffix group
3685                 for (i = 0;i < 6;i++)
3686                 {
3687                         // generate an image name based on the base and and suffix
3688                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3689                         // load it
3690                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3691                         {
3692                                 // an image loaded, make sure width and height are equal
3693                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3694                                 {
3695                                         // if this is the first image to load successfully, allocate the cubemap memory
3696                                         if (!cubemappixels && image_width >= 1)
3697                                         {
3698                                                 cubemapsize = image_width;
3699                                                 // note this clears to black, so unavailable sides are black
3700                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3701                                         }
3702                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3703                                         if (cubemappixels)
3704                                                 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);
3705                                 }
3706                                 else
3707                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3708                                 // free the image
3709                                 Mem_Free(image_buffer);
3710                         }
3711                 }
3712         }
3713         // if a cubemap loaded, upload it
3714         if (cubemappixels)
3715         {
3716                 if (developer_loading.integer)
3717                         Con_Printf("loading cubemap \"%s\"\n", basename);
3718
3719                 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);
3720                 Mem_Free(cubemappixels);
3721         }
3722         else
3723         {
3724                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3725                 if (developer_loading.integer)
3726                 {
3727                         Con_Printf("(tried tried images ");
3728                         for (j = 0;j < 3;j++)
3729                                 for (i = 0;i < 6;i++)
3730                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3731                         Con_Print(" and was unable to find any of them).\n");
3732                 }
3733         }
3734         return cubemaptexture;
3735 }
3736
3737 rtexture_t *R_GetCubemap(const char *basename)
3738 {
3739         int i;
3740         for (i = 0;i < r_texture_numcubemaps;i++)
3741                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3742                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3743         if (i >= MAX_CUBEMAPS)
3744                 return r_texture_whitecube;
3745         r_texture_numcubemaps++;
3746         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3747         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3748         return r_texture_cubemaps[i].texture;
3749 }
3750
3751 void R_FreeCubemaps(void)
3752 {
3753         int i;
3754         for (i = 0;i < r_texture_numcubemaps;i++)
3755         {
3756                 if (developer_loading.integer)
3757                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3758                 if (r_texture_cubemaps[i].texture)
3759                         R_FreeTexture(r_texture_cubemaps[i].texture);
3760         }
3761         r_texture_numcubemaps = 0;
3762 }
3763
3764 void R_Main_FreeViewCache(void)
3765 {
3766         if (r_refdef.viewcache.entityvisible)
3767                 Mem_Free(r_refdef.viewcache.entityvisible);
3768         if (r_refdef.viewcache.world_pvsbits)
3769                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3770         if (r_refdef.viewcache.world_leafvisible)
3771                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3772         if (r_refdef.viewcache.world_surfacevisible)
3773                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3774         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3775 }
3776
3777 void R_Main_ResizeViewCache(void)
3778 {
3779         int numentities = r_refdef.scene.numentities;
3780         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3781         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3782         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3783         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3784         if (r_refdef.viewcache.maxentities < numentities)
3785         {
3786                 r_refdef.viewcache.maxentities = numentities;
3787                 if (r_refdef.viewcache.entityvisible)
3788                         Mem_Free(r_refdef.viewcache.entityvisible);
3789                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3790         }
3791         if (r_refdef.viewcache.world_numclusters != numclusters)
3792         {
3793                 r_refdef.viewcache.world_numclusters = numclusters;
3794                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3795                 if (r_refdef.viewcache.world_pvsbits)
3796                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3797                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3798         }
3799         if (r_refdef.viewcache.world_numleafs != numleafs)
3800         {
3801                 r_refdef.viewcache.world_numleafs = numleafs;
3802                 if (r_refdef.viewcache.world_leafvisible)
3803                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3804                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3805         }
3806         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3807         {
3808                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3809                 if (r_refdef.viewcache.world_surfacevisible)
3810                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3811                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3812         }
3813 }
3814
3815 extern rtexture_t *loadingscreentexture;
3816 void gl_main_start(void)
3817 {
3818         loadingscreentexture = NULL;
3819         r_texture_blanknormalmap = NULL;
3820         r_texture_white = NULL;
3821         r_texture_grey128 = NULL;
3822         r_texture_black = NULL;
3823         r_texture_whitecube = NULL;
3824         r_texture_normalizationcube = NULL;
3825         r_texture_fogattenuation = NULL;
3826         r_texture_fogheighttexture = NULL;
3827         r_texture_gammaramps = NULL;
3828         r_texture_numcubemaps = 0;
3829
3830         r_loaddds = r_texture_dds_load.integer != 0;
3831         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3832
3833         switch(vid.renderpath)
3834         {
3835         case RENDERPATH_GL20:
3836         case RENDERPATH_D3D9:
3837         case RENDERPATH_D3D10:
3838         case RENDERPATH_D3D11:
3839         case RENDERPATH_SOFT:
3840         case RENDERPATH_GLES2:
3841                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3842                 Cvar_SetValueQuick(&gl_combine, 1);
3843                 Cvar_SetValueQuick(&r_glsl, 1);
3844                 r_loadnormalmap = true;
3845                 r_loadgloss = true;
3846                 r_loadfog = false;
3847                 break;
3848         case RENDERPATH_GL13:
3849                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3850                 Cvar_SetValueQuick(&gl_combine, 1);
3851                 Cvar_SetValueQuick(&r_glsl, 0);
3852                 r_loadnormalmap = false;
3853                 r_loadgloss = false;
3854                 r_loadfog = true;
3855                 break;
3856         case RENDERPATH_GL11:
3857                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3858                 Cvar_SetValueQuick(&gl_combine, 0);
3859                 Cvar_SetValueQuick(&r_glsl, 0);
3860                 r_loadnormalmap = false;
3861                 r_loadgloss = false;
3862                 r_loadfog = true;
3863                 break;
3864         }
3865
3866         R_AnimCache_Free();
3867         R_FrameData_Reset();
3868
3869         r_numqueries = 0;
3870         r_maxqueries = 0;
3871         memset(r_queries, 0, sizeof(r_queries));
3872
3873         r_qwskincache = NULL;
3874         r_qwskincache_size = 0;
3875
3876         // due to caching of texture_t references, the collision cache must be reset
3877         Collision_Cache_Reset(true);
3878
3879         // set up r_skinframe loading system for textures
3880         memset(&r_skinframe, 0, sizeof(r_skinframe));
3881         r_skinframe.loadsequence = 1;
3882         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3883
3884         r_main_texturepool = R_AllocTexturePool();
3885         R_BuildBlankTextures();
3886         R_BuildNoTexture();
3887         if (vid.support.arb_texture_cube_map)
3888         {
3889                 R_BuildWhiteCube();
3890                 R_BuildNormalizationCube();
3891         }
3892         r_texture_fogattenuation = NULL;
3893         r_texture_fogheighttexture = NULL;
3894         r_texture_gammaramps = NULL;
3895         //r_texture_fogintensity = NULL;
3896         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3897         memset(&r_waterstate, 0, sizeof(r_waterstate));
3898         r_glsl_permutation = NULL;
3899         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3900         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3901         glslshaderstring = NULL;
3902 #ifdef SUPPORTD3D
3903         r_hlsl_permutation = NULL;
3904         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3905         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3906 #endif
3907         hlslshaderstring = NULL;
3908         memset(&r_svbsp, 0, sizeof (r_svbsp));
3909
3910         r_refdef.fogmasktable_density = 0;
3911 }
3912
3913 void gl_main_shutdown(void)
3914 {
3915         R_AnimCache_Free();
3916         R_FrameData_Reset();
3917
3918         R_Main_FreeViewCache();
3919
3920         switch(vid.renderpath)
3921         {
3922         case RENDERPATH_GL11:
3923         case RENDERPATH_GL13:
3924         case RENDERPATH_GL20:
3925         case RENDERPATH_GLES2:
3926                 if (r_maxqueries)
3927                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3928                 break;
3929         case RENDERPATH_D3D9:
3930                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3931                 break;
3932         case RENDERPATH_D3D10:
3933                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3934                 break;
3935         case RENDERPATH_D3D11:
3936                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3937                 break;
3938         case RENDERPATH_SOFT:
3939                 break;
3940         }
3941
3942         r_numqueries = 0;
3943         r_maxqueries = 0;
3944         memset(r_queries, 0, sizeof(r_queries));
3945
3946         r_qwskincache = NULL;
3947         r_qwskincache_size = 0;
3948
3949         // clear out the r_skinframe state
3950         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3951         memset(&r_skinframe, 0, sizeof(r_skinframe));
3952
3953         if (r_svbsp.nodes)
3954                 Mem_Free(r_svbsp.nodes);
3955         memset(&r_svbsp, 0, sizeof (r_svbsp));
3956         R_FreeTexturePool(&r_main_texturepool);
3957         loadingscreentexture = NULL;
3958         r_texture_blanknormalmap = NULL;
3959         r_texture_white = NULL;
3960         r_texture_grey128 = NULL;
3961         r_texture_black = NULL;
3962         r_texture_whitecube = NULL;
3963         r_texture_normalizationcube = NULL;
3964         r_texture_fogattenuation = NULL;
3965         r_texture_fogheighttexture = NULL;
3966         r_texture_gammaramps = NULL;
3967         r_texture_numcubemaps = 0;
3968         //r_texture_fogintensity = NULL;
3969         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3970         memset(&r_waterstate, 0, sizeof(r_waterstate));
3971         R_GLSL_Restart_f();
3972
3973         r_glsl_permutation = NULL;
3974         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3975         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3976         glslshaderstring = NULL;
3977 #ifdef SUPPORTD3D
3978         r_hlsl_permutation = NULL;
3979         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3980         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3981 #endif
3982         hlslshaderstring = NULL;
3983 }
3984
3985 extern void CL_ParseEntityLump(char *entitystring);
3986 void gl_main_newmap(void)
3987 {
3988         // FIXME: move this code to client
3989         char *entities, entname[MAX_QPATH];
3990         if (r_qwskincache)
3991                 Mem_Free(r_qwskincache);
3992         r_qwskincache = NULL;
3993         r_qwskincache_size = 0;
3994         if (cl.worldmodel)
3995         {
3996                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3997                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3998                 {
3999                         CL_ParseEntityLump(entities);
4000                         Mem_Free(entities);
4001                         return;
4002                 }
4003                 if (cl.worldmodel->brush.entities)
4004                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4005         }
4006         R_Main_FreeViewCache();
4007
4008         R_FrameData_Reset();
4009 }
4010
4011 void GL_Main_Init(void)
4012 {
4013         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4014
4015         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4016         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4017         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4018         if (gamemode == GAME_NEHAHRA)
4019         {
4020                 Cvar_RegisterVariable (&gl_fogenable);
4021                 Cvar_RegisterVariable (&gl_fogdensity);
4022                 Cvar_RegisterVariable (&gl_fogred);
4023                 Cvar_RegisterVariable (&gl_foggreen);
4024                 Cvar_RegisterVariable (&gl_fogblue);
4025                 Cvar_RegisterVariable (&gl_fogstart);
4026                 Cvar_RegisterVariable (&gl_fogend);
4027                 Cvar_RegisterVariable (&gl_skyclip);
4028         }
4029         Cvar_RegisterVariable(&r_motionblur);
4030         Cvar_RegisterVariable(&r_motionblur_maxblur);
4031         Cvar_RegisterVariable(&r_motionblur_bmin);
4032         Cvar_RegisterVariable(&r_motionblur_vmin);
4033         Cvar_RegisterVariable(&r_motionblur_vmax);
4034         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4035         Cvar_RegisterVariable(&r_motionblur_randomize);
4036         Cvar_RegisterVariable(&r_damageblur);
4037         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4038         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4039         Cvar_RegisterVariable(&r_equalize_entities_by);
4040         Cvar_RegisterVariable(&r_equalize_entities_to);
4041         Cvar_RegisterVariable(&r_depthfirst);
4042         Cvar_RegisterVariable(&r_useinfinitefarclip);
4043         Cvar_RegisterVariable(&r_farclip_base);
4044         Cvar_RegisterVariable(&r_farclip_world);
4045         Cvar_RegisterVariable(&r_nearclip);
4046         Cvar_RegisterVariable(&r_showoverdraw);
4047         Cvar_RegisterVariable(&r_showbboxes);
4048         Cvar_RegisterVariable(&r_showsurfaces);
4049         Cvar_RegisterVariable(&r_showtris);
4050         Cvar_RegisterVariable(&r_shownormals);
4051         Cvar_RegisterVariable(&r_showlighting);
4052         Cvar_RegisterVariable(&r_showshadowvolumes);
4053         Cvar_RegisterVariable(&r_showcollisionbrushes);
4054         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4055         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4056         Cvar_RegisterVariable(&r_showdisabledepthtest);
4057         Cvar_RegisterVariable(&r_drawportals);
4058         Cvar_RegisterVariable(&r_drawentities);
4059         Cvar_RegisterVariable(&r_draw2d);
4060         Cvar_RegisterVariable(&r_drawworld);
4061         Cvar_RegisterVariable(&r_cullentities_trace);
4062         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4063         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4064         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4065         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4066         Cvar_RegisterVariable(&r_drawviewmodel);
4067         Cvar_RegisterVariable(&r_drawexteriormodel);
4068         Cvar_RegisterVariable(&r_speeds);
4069         Cvar_RegisterVariable(&r_fullbrights);
4070         Cvar_RegisterVariable(&r_wateralpha);
4071         Cvar_RegisterVariable(&r_dynamic);
4072         Cvar_RegisterVariable(&r_fakelight);
4073         Cvar_RegisterVariable(&r_fakelight_intensity);
4074         Cvar_RegisterVariable(&r_fullbright);
4075         Cvar_RegisterVariable(&r_shadows);
4076         Cvar_RegisterVariable(&r_shadows_darken);
4077         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4078         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4079         Cvar_RegisterVariable(&r_shadows_throwdistance);
4080         Cvar_RegisterVariable(&r_shadows_throwdirection);
4081         Cvar_RegisterVariable(&r_shadows_focus);
4082         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4083         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4084         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4085         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4086         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4087         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4088         Cvar_RegisterVariable(&r_fog_exp2);
4089         Cvar_RegisterVariable(&r_fog_clear);
4090         Cvar_RegisterVariable(&r_drawfog);
4091         Cvar_RegisterVariable(&r_transparentdepthmasking);
4092         Cvar_RegisterVariable(&r_texture_dds_load);
4093         Cvar_RegisterVariable(&r_texture_dds_save);
4094         Cvar_RegisterVariable(&r_texture_sRGB_2d);
4095         Cvar_RegisterVariable(&r_texture_sRGB_skin_diffuse);
4096         Cvar_RegisterVariable(&r_texture_sRGB_skin_gloss);
4097         Cvar_RegisterVariable(&r_texture_sRGB_skin_glow);
4098         Cvar_RegisterVariable(&r_texture_sRGB_skin_reflect);
4099         Cvar_RegisterVariable(&r_texture_sRGB_cubemap);
4100         Cvar_RegisterVariable(&r_texture_sRGB_skybox);
4101         Cvar_RegisterVariable(&r_textureunits);
4102         Cvar_RegisterVariable(&gl_combine);
4103         Cvar_RegisterVariable(&r_viewfbo);
4104         Cvar_RegisterVariable(&r_viewscale);
4105         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4106         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4107         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4108         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4109         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4110         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4111         Cvar_RegisterVariable(&r_glsl);
4112         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4113         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4114         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4115         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4116         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4117         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4118         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4119         Cvar_RegisterVariable(&r_glsl_postprocess);
4120         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4121         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4122         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4123         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4124         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4125         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4126         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4127         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4128
4129         Cvar_RegisterVariable(&r_water);
4130         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4131         Cvar_RegisterVariable(&r_water_clippingplanebias);
4132         Cvar_RegisterVariable(&r_water_refractdistort);
4133         Cvar_RegisterVariable(&r_water_reflectdistort);
4134         Cvar_RegisterVariable(&r_water_scissormode);
4135         Cvar_RegisterVariable(&r_lerpsprites);
4136         Cvar_RegisterVariable(&r_lerpmodels);
4137         Cvar_RegisterVariable(&r_lerplightstyles);
4138         Cvar_RegisterVariable(&r_waterscroll);
4139         Cvar_RegisterVariable(&r_bloom);
4140         Cvar_RegisterVariable(&r_bloom_colorscale);
4141         Cvar_RegisterVariable(&r_bloom_brighten);
4142         Cvar_RegisterVariable(&r_bloom_blur);
4143         Cvar_RegisterVariable(&r_bloom_resolution);
4144         Cvar_RegisterVariable(&r_bloom_colorexponent);
4145         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4146         Cvar_RegisterVariable(&r_hdr);
4147         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4148         Cvar_RegisterVariable(&r_hdr_glowintensity);
4149         Cvar_RegisterVariable(&r_hdr_range);
4150         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4151         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4152         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4153         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4154         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4155         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4156         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4157         Cvar_RegisterVariable(&developer_texturelogging);
4158         Cvar_RegisterVariable(&gl_lightmaps);
4159         Cvar_RegisterVariable(&r_test);
4160         Cvar_RegisterVariable(&r_glsl_saturation);
4161         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4162         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4163         Cvar_RegisterVariable(&r_framedatasize);
4164         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4165                 Cvar_SetValue("r_fullbrights", 0);
4166         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4167
4168         Cvar_RegisterVariable(&r_track_sprites);
4169         Cvar_RegisterVariable(&r_track_sprites_flags);
4170         Cvar_RegisterVariable(&r_track_sprites_scalew);
4171         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4172         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4173         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4174         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4175         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4176 }
4177
4178 extern void R_Textures_Init(void);
4179 extern void GL_Draw_Init(void);
4180 extern void GL_Main_Init(void);
4181 extern void R_Shadow_Init(void);
4182 extern void R_Sky_Init(void);
4183 extern void GL_Surf_Init(void);
4184 extern void R_Particles_Init(void);
4185 extern void R_Explosion_Init(void);
4186 extern void gl_backend_init(void);
4187 extern void Sbar_Init(void);
4188 extern void R_LightningBeams_Init(void);
4189 extern void Mod_RenderInit(void);
4190 extern void Font_Init(void);
4191
4192 void Render_Init(void)
4193 {
4194         gl_backend_init();
4195         R_Textures_Init();
4196         GL_Main_Init();
4197         Font_Init();
4198         GL_Draw_Init();
4199         R_Shadow_Init();
4200         R_Sky_Init();
4201         GL_Surf_Init();
4202         Sbar_Init();
4203         R_Particles_Init();
4204         R_Explosion_Init();
4205         R_LightningBeams_Init();
4206         Mod_RenderInit();
4207 }
4208
4209 /*
4210 ===============
4211 GL_Init
4212 ===============
4213 */
4214 extern char *ENGINE_EXTENSIONS;
4215 void GL_Init (void)
4216 {
4217         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4218         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4219         gl_version = (const char *)qglGetString(GL_VERSION);
4220         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4221
4222         if (!gl_extensions)
4223                 gl_extensions = "";
4224         if (!gl_platformextensions)
4225                 gl_platformextensions = "";
4226
4227         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4228         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4229         Con_Printf("GL_VERSION: %s\n", gl_version);
4230         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4231         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4232
4233         VID_CheckExtensions();
4234
4235         // LordHavoc: report supported extensions
4236         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4237
4238         // clear to black (loading plaque will be seen over this)
4239         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4240 }
4241
4242 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4243 {
4244         int i;
4245         mplane_t *p;
4246         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4247         {
4248                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4249                 if (i == 4)
4250                         continue;
4251                 p = r_refdef.view.frustum + i;
4252                 switch(p->signbits)
4253                 {
4254                 default:
4255                 case 0:
4256                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4257                                 return true;
4258                         break;
4259                 case 1:
4260                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4261                                 return true;
4262                         break;
4263                 case 2:
4264                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4265                                 return true;
4266                         break;
4267                 case 3:
4268                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4269                                 return true;
4270                         break;
4271                 case 4:
4272                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4273                                 return true;
4274                         break;
4275                 case 5:
4276                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4277                                 return true;
4278                         break;
4279                 case 6:
4280                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4281                                 return true;
4282                         break;
4283                 case 7:
4284                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4285                                 return true;
4286                         break;
4287                 }
4288         }
4289         return false;
4290 }
4291
4292 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4293 {
4294         int i;
4295         const mplane_t *p;
4296         for (i = 0;i < numplanes;i++)
4297         {
4298                 p = planes + i;
4299                 switch(p->signbits)
4300                 {
4301                 default:
4302                 case 0:
4303                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4304                                 return true;
4305                         break;
4306                 case 1:
4307                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4308                                 return true;
4309                         break;
4310                 case 2:
4311                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4312                                 return true;
4313                         break;
4314                 case 3:
4315                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4316                                 return true;
4317                         break;
4318                 case 4:
4319                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4320                                 return true;
4321                         break;
4322                 case 5:
4323                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4324                                 return true;
4325                         break;
4326                 case 6:
4327                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4328                                 return true;
4329                         break;
4330                 case 7:
4331                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4332                                 return true;
4333                         break;
4334                 }
4335         }
4336         return false;
4337 }
4338
4339 //==================================================================================
4340
4341 // LordHavoc: this stores temporary data used within the same frame
4342
4343 typedef struct r_framedata_mem_s
4344 {
4345         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4346         size_t size; // how much usable space
4347         size_t current; // how much space in use
4348         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4349         size_t wantedsize; // how much space was allocated
4350         unsigned char *data; // start of real data (16byte aligned)
4351 }
4352 r_framedata_mem_t;
4353
4354 static r_framedata_mem_t *r_framedata_mem;
4355
4356 void R_FrameData_Reset(void)
4357 {
4358         while (r_framedata_mem)
4359         {
4360                 r_framedata_mem_t *next = r_framedata_mem->purge;
4361                 Mem_Free(r_framedata_mem);
4362                 r_framedata_mem = next;
4363         }
4364 }
4365
4366 void R_FrameData_Resize(void)
4367 {
4368         size_t wantedsize;
4369         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4370         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4371         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4372         {
4373                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4374                 newmem->wantedsize = wantedsize;
4375                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4376                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4377                 newmem->current = 0;
4378                 newmem->mark = 0;
4379                 newmem->purge = r_framedata_mem;
4380                 r_framedata_mem = newmem;
4381         }
4382 }
4383
4384 void R_FrameData_NewFrame(void)
4385 {
4386         R_FrameData_Resize();
4387         if (!r_framedata_mem)
4388                 return;
4389         // if we ran out of space on the last frame, free the old memory now
4390         while (r_framedata_mem->purge)
4391         {
4392                 // repeatedly remove the second item in the list, leaving only head
4393                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4394                 Mem_Free(r_framedata_mem->purge);
4395                 r_framedata_mem->purge = next;
4396         }
4397         // reset the current mem pointer
4398         r_framedata_mem->current = 0;
4399         r_framedata_mem->mark = 0;
4400 }
4401
4402 void *R_FrameData_Alloc(size_t size)
4403 {
4404         void *data;
4405
4406         // align to 16 byte boundary - the data pointer is already aligned, so we
4407         // only need to ensure the size of every allocation is also aligned
4408         size = (size + 15) & ~15;
4409
4410         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4411         {
4412                 // emergency - we ran out of space, allocate more memory
4413                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4414                 R_FrameData_Resize();
4415         }
4416
4417         data = r_framedata_mem->data + r_framedata_mem->current;
4418         r_framedata_mem->current += size;
4419
4420         // count the usage for stats
4421         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4422         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4423
4424         return (void *)data;
4425 }
4426
4427 void *R_FrameData_Store(size_t size, void *data)
4428 {
4429         void *d = R_FrameData_Alloc(size);
4430         if (d && data)
4431                 memcpy(d, data, size);
4432         return d;
4433 }
4434
4435 void R_FrameData_SetMark(void)
4436 {
4437         if (!r_framedata_mem)
4438                 return;
4439         r_framedata_mem->mark = r_framedata_mem->current;
4440 }
4441
4442 void R_FrameData_ReturnToMark(void)
4443 {
4444         if (!r_framedata_mem)
4445                 return;
4446         r_framedata_mem->current = r_framedata_mem->mark;
4447 }
4448
4449 //==================================================================================
4450
4451 // LordHavoc: animcache originally written by Echon, rewritten since then
4452
4453 /**
4454  * Animation cache prevents re-generating mesh data for an animated model
4455  * multiple times in one frame for lighting, shadowing, reflections, etc.
4456  */
4457
4458 void R_AnimCache_Free(void)
4459 {
4460 }
4461
4462 void R_AnimCache_ClearCache(void)
4463 {
4464         int i;
4465         entity_render_t *ent;
4466
4467         for (i = 0;i < r_refdef.scene.numentities;i++)
4468         {
4469                 ent = r_refdef.scene.entities[i];
4470                 ent->animcache_vertex3f = NULL;
4471                 ent->animcache_normal3f = NULL;
4472                 ent->animcache_svector3f = NULL;
4473                 ent->animcache_tvector3f = NULL;
4474                 ent->animcache_vertexmesh = NULL;
4475                 ent->animcache_vertex3fbuffer = NULL;
4476                 ent->animcache_vertexmeshbuffer = NULL;
4477         }
4478 }
4479
4480 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4481 {
4482         int i;
4483
4484         // check if we need the meshbuffers
4485         if (!vid.useinterleavedarrays)
4486                 return;
4487
4488         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4489                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4490         // TODO: upload vertex3f buffer?
4491         if (ent->animcache_vertexmesh)
4492         {
4493                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4494                 for (i = 0;i < numvertices;i++)
4495                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4496                 if (ent->animcache_svector3f)
4497                         for (i = 0;i < numvertices;i++)
4498                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4499                 if (ent->animcache_tvector3f)
4500                         for (i = 0;i < numvertices;i++)
4501                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4502                 if (ent->animcache_normal3f)
4503                         for (i = 0;i < numvertices;i++)
4504                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4505                 // TODO: upload vertexmeshbuffer?
4506         }
4507 }
4508
4509 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4510 {
4511         dp_model_t *model = ent->model;
4512         int numvertices;
4513         // see if it's already cached this frame
4514         if (ent->animcache_vertex3f)
4515         {
4516                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4517                 if (wantnormals || wanttangents)
4518                 {
4519                         if (ent->animcache_normal3f)
4520                                 wantnormals = false;
4521                         if (ent->animcache_svector3f)
4522                                 wanttangents = false;
4523                         if (wantnormals || wanttangents)
4524                         {
4525                                 numvertices = model->surfmesh.num_vertices;
4526                                 if (wantnormals)
4527                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4528                                 if (wanttangents)
4529                                 {
4530                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4531                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4532                                 }
4533                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4534                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4535                         }
4536                 }
4537         }
4538         else
4539         {
4540                 // see if this ent is worth caching
4541                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4542                         return false;
4543                 // get some memory for this entity and generate mesh data
4544                 numvertices = model->surfmesh.num_vertices;
4545                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4546                 if (wantnormals)
4547                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4548                 if (wanttangents)
4549                 {
4550                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4551                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4552                 }
4553                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4554                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4555         }
4556         return true;
4557 }
4558
4559 void R_AnimCache_CacheVisibleEntities(void)
4560 {
4561         int i;
4562         qboolean wantnormals = true;
4563         qboolean wanttangents = !r_showsurfaces.integer;
4564
4565         switch(vid.renderpath)
4566         {
4567         case RENDERPATH_GL20:
4568         case RENDERPATH_D3D9:
4569         case RENDERPATH_D3D10:
4570         case RENDERPATH_D3D11:
4571         case RENDERPATH_GLES2:
4572                 break;
4573         case RENDERPATH_GL13:
4574         case RENDERPATH_GL11:
4575                 wanttangents = false;
4576                 break;
4577         case RENDERPATH_SOFT:
4578                 break;
4579         }
4580
4581         if (r_shownormals.integer)
4582                 wanttangents = wantnormals = true;
4583
4584         // TODO: thread this
4585         // NOTE: R_PrepareRTLights() also caches entities
4586
4587         for (i = 0;i < r_refdef.scene.numentities;i++)
4588                 if (r_refdef.viewcache.entityvisible[i])
4589                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4590 }
4591
4592 //==================================================================================
4593
4594 static void R_View_UpdateEntityLighting (void)
4595 {
4596         int i;
4597         entity_render_t *ent;
4598         vec3_t tempdiffusenormal, avg;
4599         vec_t f, fa, fd, fdd;
4600         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4601
4602         for (i = 0;i < r_refdef.scene.numentities;i++)
4603         {
4604                 ent = r_refdef.scene.entities[i];
4605
4606                 // skip unseen models
4607                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4608                         continue;
4609
4610                 // skip bsp models
4611                 if (ent->model && ent->model->brush.num_leafs)
4612                 {
4613                         // TODO: use modellight for r_ambient settings on world?
4614                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4615                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4616                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4617                         continue;
4618                 }
4619
4620                 // fetch the lighting from the worldmodel data
4621                 VectorClear(ent->modellight_ambient);
4622                 VectorClear(ent->modellight_diffuse);
4623                 VectorClear(tempdiffusenormal);
4624                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4625                 {
4626                         vec3_t org;
4627                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4628
4629                         // complete lightning for lit sprites
4630                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4631                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4632                         {
4633                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4634                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4635                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4636                         }
4637                         else
4638                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4639
4640                         if(ent->flags & RENDER_EQUALIZE)
4641                         {
4642                                 // first fix up ambient lighting...
4643                                 if(r_equalize_entities_minambient.value > 0)
4644                                 {
4645                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4646                                         if(fd > 0)
4647                                         {
4648                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4649                                                 if(fa < r_equalize_entities_minambient.value * fd)
4650                                                 {
4651                                                         // solve:
4652                                                         //   fa'/fd' = minambient
4653                                                         //   fa'+0.25*fd' = fa+0.25*fd
4654                                                         //   ...
4655                                                         //   fa' = fd' * minambient
4656                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4657                                                         //   ...
4658                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4659                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4660                                                         //   ...
4661                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4662                                                         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
4663                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4664                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4665                                                 }
4666                                         }
4667                                 }
4668
4669                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4670                                 {
4671                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4672                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4673                                         f = fa + 0.25 * fd;
4674                                         if(f > 0)
4675                                         {
4676                                                 // adjust brightness and saturation to target
4677                                                 avg[0] = avg[1] = avg[2] = fa / f;
4678                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4679                                                 avg[0] = avg[1] = avg[2] = fd / f;
4680                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4681                                         }
4682                                 }
4683                         }
4684                 }
4685                 else // highly rare
4686                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4687
4688                 // move the light direction into modelspace coordinates for lighting code
4689                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4690                 if(VectorLength2(ent->modellight_lightdir) == 0)
4691                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4692                 VectorNormalize(ent->modellight_lightdir);
4693         }
4694 }
4695
4696 #define MAX_LINEOFSIGHTTRACES 64
4697
4698 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4699 {
4700         int i;
4701         vec3_t boxmins, boxmaxs;
4702         vec3_t start;
4703         vec3_t end;
4704         dp_model_t *model = r_refdef.scene.worldmodel;
4705
4706         if (!model || !model->brush.TraceLineOfSight)
4707                 return true;
4708
4709         // expand the box a little
4710         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4711         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4712         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4713         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4714         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4715         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4716
4717         // return true if eye is inside enlarged box
4718         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4719                 return true;
4720
4721         // try center
4722         VectorCopy(eye, start);
4723         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4724         if (model->brush.TraceLineOfSight(model, start, end))
4725                 return true;
4726
4727         // try various random positions
4728         for (i = 0;i < numsamples;i++)
4729         {
4730                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4731                 if (model->brush.TraceLineOfSight(model, start, end))
4732                         return true;
4733         }
4734
4735         return false;
4736 }
4737
4738
4739 static void R_View_UpdateEntityVisible (void)
4740 {
4741         int i;
4742         int renderimask;
4743         int samples;
4744         entity_render_t *ent;
4745
4746         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4747                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4748                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4749                 :                                                          RENDER_EXTERIORMODEL;
4750         if (!r_drawviewmodel.integer)
4751                 renderimask |= RENDER_VIEWMODEL;
4752         if (!r_drawexteriormodel.integer)
4753                 renderimask |= RENDER_EXTERIORMODEL;
4754         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4755         {
4756                 // worldmodel can check visibility
4757                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4758                 for (i = 0;i < r_refdef.scene.numentities;i++)
4759                 {
4760                         ent = r_refdef.scene.entities[i];
4761                         if (!(ent->flags & renderimask))
4762                         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)))
4763                         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))
4764                                 r_refdef.viewcache.entityvisible[i] = true;
4765                 }
4766         }
4767         else
4768         {
4769                 // no worldmodel or it can't check visibility
4770                 for (i = 0;i < r_refdef.scene.numentities;i++)
4771                 {
4772                         ent = r_refdef.scene.entities[i];
4773                         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));
4774                 }
4775         }
4776         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4777                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4778         {
4779                 for (i = 0;i < r_refdef.scene.numentities;i++)
4780                 {
4781                         if (!r_refdef.viewcache.entityvisible[i])
4782                                 continue;
4783                         ent = r_refdef.scene.entities[i];
4784                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4785                         {
4786                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4787                                 if (samples < 0)
4788                                         continue; // temp entities do pvs only
4789                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4790                                         ent->last_trace_visibility = realtime;
4791                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4792                                         r_refdef.viewcache.entityvisible[i] = 0;
4793                         }
4794                 }
4795         }
4796 }
4797
4798 /// only used if skyrendermasked, and normally returns false
4799 int R_DrawBrushModelsSky (void)
4800 {
4801         int i, sky;
4802         entity_render_t *ent;
4803
4804         sky = false;
4805         for (i = 0;i < r_refdef.scene.numentities;i++)
4806         {
4807                 if (!r_refdef.viewcache.entityvisible[i])
4808                         continue;
4809                 ent = r_refdef.scene.entities[i];
4810                 if (!ent->model || !ent->model->DrawSky)
4811                         continue;
4812                 ent->model->DrawSky(ent);
4813                 sky = true;
4814         }
4815         return sky;
4816 }
4817
4818 static void R_DrawNoModel(entity_render_t *ent);
4819 static void R_DrawModels(void)
4820 {
4821         int i;
4822         entity_render_t *ent;
4823
4824         for (i = 0;i < r_refdef.scene.numentities;i++)
4825         {
4826                 if (!r_refdef.viewcache.entityvisible[i])
4827                         continue;
4828                 ent = r_refdef.scene.entities[i];
4829                 r_refdef.stats.entities++;
4830                 if (ent->model && ent->model->Draw != NULL)
4831                         ent->model->Draw(ent);
4832                 else
4833                         R_DrawNoModel(ent);
4834         }
4835 }
4836
4837 static void R_DrawModelsDepth(void)
4838 {
4839         int i;
4840         entity_render_t *ent;
4841
4842         for (i = 0;i < r_refdef.scene.numentities;i++)
4843         {
4844                 if (!r_refdef.viewcache.entityvisible[i])
4845                         continue;
4846                 ent = r_refdef.scene.entities[i];
4847                 if (ent->model && ent->model->DrawDepth != NULL)
4848                         ent->model->DrawDepth(ent);
4849         }
4850 }
4851
4852 static void R_DrawModelsDebug(void)
4853 {
4854         int i;
4855         entity_render_t *ent;
4856
4857         for (i = 0;i < r_refdef.scene.numentities;i++)
4858         {
4859                 if (!r_refdef.viewcache.entityvisible[i])
4860                         continue;
4861                 ent = r_refdef.scene.entities[i];
4862                 if (ent->model && ent->model->DrawDebug != NULL)
4863                         ent->model->DrawDebug(ent);
4864         }
4865 }
4866
4867 static void R_DrawModelsAddWaterPlanes(void)
4868 {
4869         int i;
4870         entity_render_t *ent;
4871
4872         for (i = 0;i < r_refdef.scene.numentities;i++)
4873         {
4874                 if (!r_refdef.viewcache.entityvisible[i])
4875                         continue;
4876                 ent = r_refdef.scene.entities[i];
4877                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4878                         ent->model->DrawAddWaterPlanes(ent);
4879         }
4880 }
4881
4882 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4883 {
4884         if (r_hdr_irisadaptation.integer)
4885         {
4886                 vec3_t ambient;
4887                 vec3_t diffuse;
4888                 vec3_t diffusenormal;
4889                 vec_t brightness;
4890                 vec_t goal;
4891                 vec_t adjust;
4892                 vec_t current;
4893                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4894                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4895                 brightness = max(0.0000001f, brightness);
4896                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4897                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4898                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4899                 current = r_hdr_irisadaptation_value.value;
4900                 if (current < goal)
4901                         current = min(current + adjust, goal);
4902                 else if (current > goal)
4903                         current = max(current - adjust, goal);
4904                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4905                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4906         }
4907         else if (r_hdr_irisadaptation_value.value != 1.0f)
4908                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4909 }
4910
4911 static void R_View_SetFrustum(const int *scissor)
4912 {
4913         int i;
4914         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4915         vec3_t forward, left, up, origin, v;
4916
4917         if(scissor)
4918         {
4919                 // flipped x coordinates (because x points left here)
4920                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4921                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4922
4923                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4924                 switch(vid.renderpath)
4925                 {
4926                         case RENDERPATH_D3D9:
4927                         case RENDERPATH_D3D10:
4928                         case RENDERPATH_D3D11:
4929                                 // non-flipped y coordinates
4930                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4931                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4932                                 break;
4933                         case RENDERPATH_SOFT:
4934                         case RENDERPATH_GL11:
4935                         case RENDERPATH_GL13:
4936                         case RENDERPATH_GL20:
4937                         case RENDERPATH_GLES2:
4938                                 // non-flipped y coordinates
4939                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4940                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4941                                 break;
4942                 }
4943         }
4944
4945         // we can't trust r_refdef.view.forward and friends in reflected scenes
4946         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4947
4948 #if 0
4949         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4950         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4951         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4952         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4953         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4954         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4955         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4956         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4957         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4958         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4959         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4960         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4961 #endif
4962
4963 #if 0
4964         zNear = r_refdef.nearclip;
4965         nudge = 1.0 - 1.0 / (1<<23);
4966         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4967         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4968         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4969         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4970         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4971         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4972         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4973         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4974 #endif
4975
4976
4977
4978 #if 0
4979         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4980         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4981         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4982         r_refdef.view.frustum[0].dist = m[15] - m[12];
4983
4984         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4985         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4986         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4987         r_refdef.view.frustum[1].dist = m[15] + m[12];
4988
4989         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4990         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4991         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4992         r_refdef.view.frustum[2].dist = m[15] - m[13];
4993
4994         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4995         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4996         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4997         r_refdef.view.frustum[3].dist = m[15] + m[13];
4998
4999         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5000         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5001         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5002         r_refdef.view.frustum[4].dist = m[15] - m[14];
5003
5004         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5005         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5006         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5007         r_refdef.view.frustum[5].dist = m[15] + m[14];
5008 #endif
5009
5010         if (r_refdef.view.useperspective)
5011         {
5012                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5013                 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]);
5014                 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]);
5015                 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]);
5016                 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]);
5017
5018                 // then the normals from the corners relative to origin
5019                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5020                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5021                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5022                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5023
5024                 // in a NORMAL view, forward cross left == up
5025                 // in a REFLECTED view, forward cross left == down
5026                 // so our cross products above need to be adjusted for a left handed coordinate system
5027                 CrossProduct(forward, left, v);
5028                 if(DotProduct(v, up) < 0)
5029                 {
5030                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5031                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5032                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5033                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5034                 }
5035
5036                 // Leaving those out was a mistake, those were in the old code, and they
5037                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5038                 // I couldn't reproduce it after adding those normalizations. --blub
5039                 VectorNormalize(r_refdef.view.frustum[0].normal);
5040                 VectorNormalize(r_refdef.view.frustum[1].normal);
5041                 VectorNormalize(r_refdef.view.frustum[2].normal);
5042                 VectorNormalize(r_refdef.view.frustum[3].normal);
5043
5044                 // make the corners absolute
5045                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5046                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5047                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5048                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5049
5050                 // one more normal
5051                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5052
5053                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5054                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5055                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5056                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5057                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5058         }
5059         else
5060         {
5061                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5062                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5063                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5064                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5065                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5066                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5067                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5068                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5069                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5070                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5071         }
5072         r_refdef.view.numfrustumplanes = 5;
5073
5074         if (r_refdef.view.useclipplane)
5075         {
5076                 r_refdef.view.numfrustumplanes = 6;
5077                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5078         }
5079
5080         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5081                 PlaneClassify(r_refdef.view.frustum + i);
5082
5083         // LordHavoc: note to all quake engine coders, Quake had a special case
5084         // for 90 degrees which assumed a square view (wrong), so I removed it,
5085         // Quake2 has it disabled as well.
5086
5087         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5088         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5089         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5090         //PlaneClassify(&frustum[0]);
5091
5092         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5093         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5094         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5095         //PlaneClassify(&frustum[1]);
5096
5097         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5098         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5099         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5100         //PlaneClassify(&frustum[2]);
5101
5102         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5103         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5104         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5105         //PlaneClassify(&frustum[3]);
5106
5107         // nearclip plane
5108         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5109         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5110         //PlaneClassify(&frustum[4]);
5111 }
5112
5113 void R_View_UpdateWithScissor(const int *myscissor)
5114 {
5115         R_Main_ResizeViewCache();
5116         R_View_SetFrustum(myscissor);
5117         R_View_WorldVisibility(r_refdef.view.useclipplane);
5118         R_View_UpdateEntityVisible();
5119         R_View_UpdateEntityLighting();
5120 }
5121
5122 void R_View_Update(void)
5123 {
5124         R_Main_ResizeViewCache();
5125         R_View_SetFrustum(NULL);
5126         R_View_WorldVisibility(r_refdef.view.useclipplane);
5127         R_View_UpdateEntityVisible();
5128         R_View_UpdateEntityLighting();
5129 }
5130
5131 float viewscalefpsadjusted = 1.0f;
5132
5133 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5134 {
5135         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5136         scale = bound(0.03125f, scale, 1.0f);
5137         *outwidth = (int)ceil(width * scale);
5138         *outheight = (int)ceil(height * scale);
5139 }
5140
5141 void R_Mesh_SetMainRenderTargets(void)
5142 {
5143         if (r_bloomstate.fbo_framebuffer)
5144                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5145         else
5146                 R_Mesh_ResetRenderTargets();
5147 }
5148
5149 void R_SetupView(qboolean allowwaterclippingplane)
5150 {
5151         const float *customclipplane = NULL;
5152         float plane[4];
5153         int scaledwidth, scaledheight;
5154         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5155         {
5156                 // LordHavoc: couldn't figure out how to make this approach the
5157                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5158                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5159                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5160                         dist = r_refdef.view.clipplane.dist;
5161                 plane[0] = r_refdef.view.clipplane.normal[0];
5162                 plane[1] = r_refdef.view.clipplane.normal[1];
5163                 plane[2] = r_refdef.view.clipplane.normal[2];
5164                 plane[3] = -dist;
5165                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5166         }
5167
5168         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5169         if (!r_refdef.view.useperspective)
5170                 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);
5171         else if (vid.stencil && r_useinfinitefarclip.integer)
5172                 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);
5173         else
5174                 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);
5175         R_Mesh_SetMainRenderTargets();
5176         R_SetViewport(&r_refdef.view.viewport);
5177         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5178         {
5179                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5180                 float screenplane[4];
5181                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5182                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5183                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5184                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5185                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5186         }
5187 }
5188
5189 void R_EntityMatrix(const matrix4x4_t *matrix)
5190 {
5191         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5192         {
5193                 gl_modelmatrixchanged = false;
5194                 gl_modelmatrix = *matrix;
5195                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5196                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5197                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5198                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5199                 CHECKGLERROR
5200                 switch(vid.renderpath)
5201                 {
5202                 case RENDERPATH_D3D9:
5203 #ifdef SUPPORTD3D
5204                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5205                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5206 #endif
5207                         break;
5208                 case RENDERPATH_D3D10:
5209                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5210                         break;
5211                 case RENDERPATH_D3D11:
5212                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5213                         break;
5214                 case RENDERPATH_GL13:
5215                 case RENDERPATH_GL11:
5216                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5217                         break;
5218                 case RENDERPATH_SOFT:
5219                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5220                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5221                         break;
5222                 case RENDERPATH_GL20:
5223                 case RENDERPATH_GLES2:
5224                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5225                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5226                         break;
5227                 }
5228         }
5229 }
5230
5231 void R_ResetViewRendering2D(void)
5232 {
5233         r_viewport_t viewport;
5234         DrawQ_Finish();
5235
5236         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5237         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);
5238         R_Mesh_ResetRenderTargets();
5239         R_SetViewport(&viewport);
5240         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5241         GL_Color(1, 1, 1, 1);
5242         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5243         GL_BlendFunc(GL_ONE, GL_ZERO);
5244         GL_ScissorTest(false);
5245         GL_DepthMask(false);
5246         GL_DepthRange(0, 1);
5247         GL_DepthTest(false);
5248         GL_DepthFunc(GL_LEQUAL);
5249         R_EntityMatrix(&identitymatrix);
5250         R_Mesh_ResetTextureState();
5251         GL_PolygonOffset(0, 0);
5252         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5253         switch(vid.renderpath)
5254         {
5255         case RENDERPATH_GL11:
5256         case RENDERPATH_GL13:
5257         case RENDERPATH_GL20:
5258         case RENDERPATH_GLES2:
5259                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5260                 break;
5261         case RENDERPATH_D3D9:
5262         case RENDERPATH_D3D10:
5263         case RENDERPATH_D3D11:
5264         case RENDERPATH_SOFT:
5265                 break;
5266         }
5267         GL_CullFace(GL_NONE);
5268 }
5269
5270 void R_ResetViewRendering3D(void)
5271 {
5272         DrawQ_Finish();
5273
5274         R_SetupView(true);
5275         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5276         GL_Color(1, 1, 1, 1);
5277         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5278         GL_BlendFunc(GL_ONE, GL_ZERO);
5279         GL_ScissorTest(true);
5280         GL_DepthMask(true);
5281         GL_DepthRange(0, 1);
5282         GL_DepthTest(true);
5283         GL_DepthFunc(GL_LEQUAL);
5284         R_EntityMatrix(&identitymatrix);
5285         R_Mesh_ResetTextureState();
5286         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5287         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5288         switch(vid.renderpath)
5289         {
5290         case RENDERPATH_GL11:
5291         case RENDERPATH_GL13:
5292         case RENDERPATH_GL20:
5293         case RENDERPATH_GLES2:
5294                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5295                 break;
5296         case RENDERPATH_D3D9:
5297         case RENDERPATH_D3D10:
5298         case RENDERPATH_D3D11:
5299         case RENDERPATH_SOFT:
5300                 break;
5301         }
5302         GL_CullFace(r_refdef.view.cullface_back);
5303 }
5304
5305 /*
5306 ================
5307 R_RenderView_UpdateViewVectors
5308 ================
5309 */
5310 static void R_RenderView_UpdateViewVectors(void)
5311 {
5312         // break apart the view matrix into vectors for various purposes
5313         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5314         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5315         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5316         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5317         // make an inverted copy of the view matrix for tracking sprites
5318         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5319 }
5320
5321 void R_RenderScene(void);
5322 void R_RenderWaterPlanes(void);
5323
5324 static void R_Water_StartFrame(void)
5325 {
5326         int i;
5327         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5328         r_waterstate_waterplane_t *p;
5329
5330         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5331                 return;
5332
5333         switch(vid.renderpath)
5334         {
5335         case RENDERPATH_GL20:
5336         case RENDERPATH_D3D9:
5337         case RENDERPATH_D3D10:
5338         case RENDERPATH_D3D11:
5339         case RENDERPATH_SOFT:
5340         case RENDERPATH_GLES2:
5341                 break;
5342         case RENDERPATH_GL13:
5343         case RENDERPATH_GL11:
5344                 return;
5345         }
5346
5347         // set waterwidth and waterheight to the water resolution that will be
5348         // used (often less than the screen resolution for faster rendering)
5349         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5350         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5351
5352         // calculate desired texture sizes
5353         // can't use water if the card does not support the texture size
5354         if (!r_water.integer || r_showsurfaces.integer)
5355                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5356         else if (vid.support.arb_texture_non_power_of_two)
5357         {
5358                 texturewidth = waterwidth;
5359                 textureheight = waterheight;
5360                 camerawidth = waterwidth;
5361                 cameraheight = waterheight;
5362         }
5363         else
5364         {
5365                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5366                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5367                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5368                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5369         }
5370
5371         // allocate textures as needed
5372         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5373         {
5374                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5375                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5376                 {
5377                         if (p->texture_refraction)
5378                                 R_FreeTexture(p->texture_refraction);
5379                         p->texture_refraction = NULL;
5380                         if (p->texture_reflection)
5381                                 R_FreeTexture(p->texture_reflection);
5382                         p->texture_reflection = NULL;
5383                         if (p->texture_camera)
5384                                 R_FreeTexture(p->texture_camera);
5385                         p->texture_camera = NULL;
5386                 }
5387                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5388                 r_waterstate.texturewidth = texturewidth;
5389                 r_waterstate.textureheight = textureheight;
5390                 r_waterstate.camerawidth = camerawidth;
5391                 r_waterstate.cameraheight = cameraheight;
5392         }
5393
5394         if (r_waterstate.texturewidth)
5395         {
5396                 r_waterstate.enabled = true;
5397
5398                 // when doing a reduced render (HDR) we want to use a smaller area
5399                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5400                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5401
5402                 // set up variables that will be used in shader setup
5403                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5404                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5405                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5406                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5407         }
5408
5409         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5410         r_waterstate.numwaterplanes = 0;
5411 }
5412
5413 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5414 {
5415         int triangleindex, planeindex;
5416         const int *e;
5417         vec3_t vert[3];
5418         vec3_t normal;
5419         vec3_t center;
5420         mplane_t plane;
5421         r_waterstate_waterplane_t *p;
5422         texture_t *t = R_GetCurrentTexture(surface->texture);
5423
5424         // just use the first triangle with a valid normal for any decisions
5425         VectorClear(normal);
5426         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5427         {
5428                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5429                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5430                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5431                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5432                 if (VectorLength2(normal) >= 0.001)
5433                         break;
5434         }
5435
5436         VectorCopy(normal, plane.normal);
5437         VectorNormalize(plane.normal);
5438         plane.dist = DotProduct(vert[0], plane.normal);
5439         PlaneClassify(&plane);
5440         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5441         {
5442                 // skip backfaces (except if nocullface is set)
5443                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5444                         return;
5445                 VectorNegate(plane.normal, plane.normal);
5446                 plane.dist *= -1;
5447                 PlaneClassify(&plane);
5448         }
5449
5450
5451         // find a matching plane if there is one
5452         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5453                 if(p->camera_entity == t->camera_entity)
5454                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5455                                 break;
5456         if (planeindex >= r_waterstate.maxwaterplanes)
5457                 return; // nothing we can do, out of planes
5458
5459         // if this triangle does not fit any known plane rendered this frame, add one
5460         if (planeindex >= r_waterstate.numwaterplanes)
5461         {
5462                 // store the new plane
5463                 r_waterstate.numwaterplanes++;
5464                 p->plane = plane;
5465                 // clear materialflags and pvs
5466                 p->materialflags = 0;
5467                 p->pvsvalid = false;
5468                 p->camera_entity = t->camera_entity;
5469                 VectorCopy(surface->mins, p->mins);
5470                 VectorCopy(surface->maxs, p->maxs);
5471         }
5472         else
5473         {
5474                 // merge mins/maxs
5475                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5476                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5477                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5478                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5479                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5480                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5481         }
5482         // merge this surface's materialflags into the waterplane
5483         p->materialflags |= t->currentmaterialflags;
5484         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5485         {
5486                 // merge this surface's PVS into the waterplane
5487                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5488                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5489                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5490                 {
5491                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5492                         p->pvsvalid = true;
5493                 }
5494         }
5495 }
5496
5497 static void R_Water_ProcessPlanes(void)
5498 {
5499         int myscissor[4];
5500         r_refdef_view_t originalview;
5501         r_refdef_view_t myview;
5502         int planeindex;
5503         r_waterstate_waterplane_t *p;
5504         vec3_t visorigin;
5505
5506         originalview = r_refdef.view;
5507
5508         // make sure enough textures are allocated
5509         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5510         {
5511                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5512                 {
5513                         if (!p->texture_refraction)
5514                                 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);
5515                         if (!p->texture_refraction)
5516                                 goto error;
5517                 }
5518                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5519                 {
5520                         if (!p->texture_camera)
5521                                 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);
5522                         if (!p->texture_camera)
5523                                 goto error;
5524                 }
5525
5526                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5527                 {
5528                         if (!p->texture_reflection)
5529                                 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);
5530                         if (!p->texture_reflection)
5531                                 goto error;
5532                 }
5533         }
5534
5535         // render views
5536         r_refdef.view = originalview;
5537         r_refdef.view.showdebug = false;
5538         r_refdef.view.width = r_waterstate.waterwidth;
5539         r_refdef.view.height = r_waterstate.waterheight;
5540         r_refdef.view.useclipplane = true;
5541         myview = r_refdef.view;
5542         r_waterstate.renderingscene = true;
5543         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5544         {
5545                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5546                 {
5547                         r_refdef.view = myview;
5548                         if(r_water_scissormode.integer)
5549                         {
5550                                 R_SetupView(true);
5551                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5552                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5553                         }
5554
5555                         // render reflected scene and copy into texture
5556                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5557                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5558                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5559                         r_refdef.view.clipplane = p->plane;
5560
5561                         // reverse the cullface settings for this render
5562                         r_refdef.view.cullface_front = GL_FRONT;
5563                         r_refdef.view.cullface_back = GL_BACK;
5564                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5565                         {
5566                                 r_refdef.view.usecustompvs = true;
5567                                 if (p->pvsvalid)
5568                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5569                                 else
5570                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5571                         }
5572
5573                         R_ResetViewRendering3D();
5574                         R_ClearScreen(r_refdef.fogenabled);
5575                         if(r_water_scissormode.integer & 2)
5576                                 R_View_UpdateWithScissor(myscissor);
5577                         else
5578                                 R_View_Update();
5579                         if(r_water_scissormode.integer & 1)
5580                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5581                         R_RenderScene();
5582
5583                         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);
5584                 }
5585
5586                 // render the normal view scene and copy into texture
5587                 // (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)
5588                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5589                 {
5590                         r_refdef.view = myview;
5591                         if(r_water_scissormode.integer)
5592                         {
5593                                 R_SetupView(true);
5594                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5595                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5596                         }
5597
5598                         r_waterstate.renderingrefraction = true;
5599
5600                         r_refdef.view.clipplane = p->plane;
5601                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5602                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5603
5604                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5605                         {
5606                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5607                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5608                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5609                                 R_RenderView_UpdateViewVectors();
5610                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5611                                 {
5612                                         r_refdef.view.usecustompvs = true;
5613                                         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);
5614                                 }
5615                         }
5616
5617                         PlaneClassify(&r_refdef.view.clipplane);
5618
5619                         R_ResetViewRendering3D();
5620                         R_ClearScreen(r_refdef.fogenabled);
5621                         if(r_water_scissormode.integer & 2)
5622                                 R_View_UpdateWithScissor(myscissor);
5623                         else
5624                                 R_View_Update();
5625                         if(r_water_scissormode.integer & 1)
5626                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5627                         R_RenderScene();
5628
5629                         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);
5630                         r_waterstate.renderingrefraction = false;
5631                 }
5632                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5633                 {
5634                         r_refdef.view = myview;
5635
5636                         r_refdef.view.clipplane = p->plane;
5637                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5638                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5639
5640                         r_refdef.view.width = r_waterstate.camerawidth;
5641                         r_refdef.view.height = r_waterstate.cameraheight;
5642                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5643                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5644
5645                         if(p->camera_entity)
5646                         {
5647                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5648                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5649                         }
5650
5651                         // note: all of the view is used for displaying... so
5652                         // there is no use in scissoring
5653
5654                         // reverse the cullface settings for this render
5655                         r_refdef.view.cullface_front = GL_FRONT;
5656                         r_refdef.view.cullface_back = GL_BACK;
5657                         // also reverse the view matrix
5658                         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
5659                         R_RenderView_UpdateViewVectors();
5660                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5661                         {
5662                                 r_refdef.view.usecustompvs = true;
5663                                 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);
5664                         }
5665                         
5666                         // camera needs no clipplane
5667                         r_refdef.view.useclipplane = false;
5668
5669                         PlaneClassify(&r_refdef.view.clipplane);
5670
5671                         R_ResetViewRendering3D();
5672                         R_ClearScreen(r_refdef.fogenabled);
5673                         R_View_Update();
5674                         R_RenderScene();
5675
5676                         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);
5677                         r_waterstate.renderingrefraction = false;
5678                 }
5679
5680         }
5681         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5682         r_waterstate.renderingscene = false;
5683         r_refdef.view = originalview;
5684         R_ResetViewRendering3D();
5685         R_ClearScreen(r_refdef.fogenabled);
5686         R_View_Update();
5687         return;
5688 error:
5689         r_refdef.view = originalview;
5690         r_waterstate.renderingscene = false;
5691         Cvar_SetValueQuick(&r_water, 0);
5692         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5693         return;
5694 }
5695
5696 void R_Bloom_StartFrame(void)
5697 {
5698         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5699         int viewwidth, viewheight;
5700         textype_t textype;
5701
5702         if (r_viewscale_fpsscaling.integer)
5703         {
5704                 double actualframetime;
5705                 double targetframetime;
5706                 double adjust;
5707                 actualframetime = r_refdef.lastdrawscreentime;
5708                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5709                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5710                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5711                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5712                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5713                 viewscalefpsadjusted += adjust;
5714                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5715         }
5716         else
5717                 viewscalefpsadjusted = 1.0f;
5718
5719         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5720
5721         switch(vid.renderpath)
5722         {
5723         case RENDERPATH_GL20:
5724         case RENDERPATH_D3D9:
5725         case RENDERPATH_D3D10:
5726         case RENDERPATH_D3D11:
5727         case RENDERPATH_SOFT:
5728         case RENDERPATH_GLES2:
5729                 break;
5730         case RENDERPATH_GL13:
5731         case RENDERPATH_GL11:
5732                 return;
5733         }
5734
5735         // set bloomwidth and bloomheight to the bloom resolution that will be
5736         // used (often less than the screen resolution for faster rendering)
5737         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5738         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5739         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5740         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5741         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5742
5743         // calculate desired texture sizes
5744         if (vid.support.arb_texture_non_power_of_two)
5745         {
5746                 screentexturewidth = vid.width;
5747                 screentextureheight = vid.height;
5748                 bloomtexturewidth = r_bloomstate.bloomwidth;
5749                 bloomtextureheight = r_bloomstate.bloomheight;
5750         }
5751         else
5752         {
5753                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5754                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5755                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5756                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5757         }
5758
5759         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))
5760         {
5761                 Cvar_SetValueQuick(&r_hdr, 0);
5762                 Cvar_SetValueQuick(&r_bloom, 0);
5763                 Cvar_SetValueQuick(&r_motionblur, 0);
5764                 Cvar_SetValueQuick(&r_damageblur, 0);
5765         }
5766
5767         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)
5768                 screentexturewidth = screentextureheight = 0;
5769         if (!r_hdr.integer && !r_bloom.integer)
5770                 bloomtexturewidth = bloomtextureheight = 0;
5771
5772         textype = TEXTYPE_COLORBUFFER;
5773         switch (vid.renderpath)
5774         {
5775         case RENDERPATH_GL20:
5776         case RENDERPATH_GLES2:
5777                 if (vid.support.ext_framebuffer_object)
5778                 {
5779                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5780                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5781                 }
5782                 break;
5783         case RENDERPATH_D3D9:
5784         case RENDERPATH_D3D10:
5785         case RENDERPATH_D3D11:
5786         case RENDERPATH_SOFT:
5787         case RENDERPATH_GL13:
5788         case RENDERPATH_GL11:
5789                 break;
5790         }
5791
5792         // allocate textures as needed
5793         if (r_bloomstate.screentexturewidth != screentexturewidth
5794          || r_bloomstate.screentextureheight != screentextureheight
5795          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5796          || r_bloomstate.bloomtextureheight != bloomtextureheight
5797          || r_bloomstate.texturetype != textype
5798          || r_bloomstate.viewfbo != r_viewfbo.integer)
5799         {
5800                 if (r_bloomstate.texture_bloom)
5801                         R_FreeTexture(r_bloomstate.texture_bloom);
5802                 r_bloomstate.texture_bloom = NULL;
5803                 if (r_bloomstate.texture_screen)
5804                         R_FreeTexture(r_bloomstate.texture_screen);
5805                 r_bloomstate.texture_screen = NULL;
5806                 if (r_bloomstate.fbo_framebuffer)
5807                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5808                 r_bloomstate.fbo_framebuffer = 0;
5809                 if (r_bloomstate.texture_framebuffercolor)
5810                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5811                 r_bloomstate.texture_framebuffercolor = NULL;
5812                 if (r_bloomstate.texture_framebufferdepth)
5813                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5814                 r_bloomstate.texture_framebufferdepth = NULL;
5815                 r_bloomstate.screentexturewidth = screentexturewidth;
5816                 r_bloomstate.screentextureheight = screentextureheight;
5817                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5818                         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);
5819                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5820                 {
5821                         // FIXME: choose depth bits based on a cvar
5822                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5823                         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);
5824                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5825                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5826                         // render depth into one texture and normalmap into the other
5827                         if (qglDrawBuffer)
5828                         {
5829                                 int status;
5830                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5831                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5832                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5833                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5834                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5835                         }
5836                 }
5837                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5838                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5839                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5840                         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);
5841                 r_bloomstate.viewfbo = r_viewfbo.integer;
5842                 r_bloomstate.texturetype = textype;
5843         }
5844
5845         // when doing a reduced render (HDR) we want to use a smaller area
5846         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5847         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5848         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5849         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5850         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5851
5852         // set up a texcoord array for the full resolution screen image
5853         // (we have to keep this around to copy back during final render)
5854         r_bloomstate.screentexcoord2f[0] = 0;
5855         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5856         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5857         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5858         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5859         r_bloomstate.screentexcoord2f[5] = 0;
5860         r_bloomstate.screentexcoord2f[6] = 0;
5861         r_bloomstate.screentexcoord2f[7] = 0;
5862
5863         // set up a texcoord array for the reduced resolution bloom image
5864         // (which will be additive blended over the screen image)
5865         r_bloomstate.bloomtexcoord2f[0] = 0;
5866         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5867         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5868         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5869         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5870         r_bloomstate.bloomtexcoord2f[5] = 0;
5871         r_bloomstate.bloomtexcoord2f[6] = 0;
5872         r_bloomstate.bloomtexcoord2f[7] = 0;
5873
5874         switch(vid.renderpath)
5875         {
5876         case RENDERPATH_GL11:
5877         case RENDERPATH_GL13:
5878         case RENDERPATH_GL20:
5879         case RENDERPATH_SOFT:
5880         case RENDERPATH_GLES2:
5881                 break;
5882         case RENDERPATH_D3D9:
5883         case RENDERPATH_D3D10:
5884         case RENDERPATH_D3D11:
5885                 {
5886                         int i;
5887                         for (i = 0;i < 4;i++)
5888                         {
5889                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5890                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5891                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5892                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5893                         }
5894                 }
5895                 break;
5896         }
5897
5898         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5899         {
5900                 r_bloomstate.enabled = true;
5901                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5902         }
5903
5904         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);
5905
5906         if (r_bloomstate.fbo_framebuffer)
5907                 r_refdef.view.clear = true;
5908 }
5909
5910 void R_Bloom_CopyBloomTexture(float colorscale)
5911 {
5912         r_refdef.stats.bloom++;
5913
5914         // scale down screen texture to the bloom texture size
5915         CHECKGLERROR
5916         R_Mesh_SetMainRenderTargets();
5917         R_SetViewport(&r_bloomstate.viewport);
5918         GL_BlendFunc(GL_ONE, GL_ZERO);
5919         GL_Color(colorscale, colorscale, colorscale, 1);
5920         // 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...
5921         switch(vid.renderpath)
5922         {
5923         case RENDERPATH_GL11:
5924         case RENDERPATH_GL13:
5925         case RENDERPATH_GL20:
5926         case RENDERPATH_SOFT:
5927         case RENDERPATH_GLES2:
5928                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5929                 break;
5930         case RENDERPATH_D3D9:
5931         case RENDERPATH_D3D10:
5932         case RENDERPATH_D3D11:
5933                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5934                 break;
5935         }
5936         // TODO: do boxfilter scale-down in shader?
5937         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5938         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5939         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5940
5941         // we now have a bloom image in the framebuffer
5942         // copy it into the bloom image texture for later processing
5943         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);
5944         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5945 }
5946
5947 void R_Bloom_CopyHDRTexture(void)
5948 {
5949         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);
5950         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5951 }
5952
5953 void R_Bloom_MakeTexture(void)
5954 {
5955         int x, range, dir;
5956         float xoffset, yoffset, r, brighten;
5957
5958         r_refdef.stats.bloom++;
5959
5960         R_ResetViewRendering2D();
5961
5962         // we have a bloom image in the framebuffer
5963         CHECKGLERROR
5964         R_SetViewport(&r_bloomstate.viewport);
5965
5966         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5967         {
5968                 x *= 2;
5969                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5970                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5971                 GL_Color(r,r,r,1);
5972                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5973                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5974                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5975                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5976
5977                 // copy the vertically blurred bloom view to a texture
5978                 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);
5979                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5980         }
5981
5982         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5983         brighten = r_bloom_brighten.value;
5984         if (r_bloomstate.hdr)
5985                 brighten *= r_hdr_range.value;
5986         brighten = sqrt(brighten);
5987         if(range >= 1)
5988                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5989         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5990
5991         for (dir = 0;dir < 2;dir++)
5992         {
5993                 // blend on at multiple vertical offsets to achieve a vertical blur
5994                 // TODO: do offset blends using GLSL
5995                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5996                 GL_BlendFunc(GL_ONE, GL_ZERO);
5997                 for (x = -range;x <= range;x++)
5998                 {
5999                         if (!dir){xoffset = 0;yoffset = x;}
6000                         else {xoffset = x;yoffset = 0;}
6001                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6002                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6003                         // compute a texcoord array with the specified x and y offset
6004                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6005                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6006                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6007                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6008                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6009                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6010                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6011                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6012                         // this r value looks like a 'dot' particle, fading sharply to
6013                         // black at the edges
6014                         // (probably not realistic but looks good enough)
6015                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6016                         //r = brighten/(range*2+1);
6017                         r = brighten / (range * 2 + 1);
6018                         if(range >= 1)
6019                                 r *= (1 - x*x/(float)(range*range));
6020                         GL_Color(r, r, r, 1);
6021                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6022                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6023                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6024                         GL_BlendFunc(GL_ONE, GL_ONE);
6025                 }
6026
6027                 // copy the vertically blurred bloom view to a texture
6028                 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);
6029                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6030         }
6031 }
6032
6033 void R_HDR_RenderBloomTexture(void)
6034 {
6035         int oldwidth, oldheight;
6036         float oldcolorscale;
6037         qboolean oldwaterstate;
6038
6039         oldwaterstate = r_waterstate.enabled;
6040         oldcolorscale = r_refdef.view.colorscale;
6041         oldwidth = r_refdef.view.width;
6042         oldheight = r_refdef.view.height;
6043         r_refdef.view.width = r_bloomstate.bloomwidth;
6044         r_refdef.view.height = r_bloomstate.bloomheight;
6045
6046         if(r_hdr.integer < 2)
6047                 r_waterstate.enabled = false;
6048
6049         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6050         // TODO: add exposure compensation features
6051         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6052
6053         r_refdef.view.showdebug = false;
6054         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6055
6056         R_ResetViewRendering3D();
6057
6058         R_ClearScreen(r_refdef.fogenabled);
6059         if (r_timereport_active)
6060                 R_TimeReport("HDRclear");
6061
6062         R_View_Update();
6063         if (r_timereport_active)
6064                 R_TimeReport("visibility");
6065
6066         // only do secondary renders with HDR if r_hdr is 2 or higher
6067         r_waterstate.numwaterplanes = 0;
6068         if (r_waterstate.enabled)
6069                 R_RenderWaterPlanes();
6070
6071         r_refdef.view.showdebug = true;
6072         R_RenderScene();
6073         r_waterstate.numwaterplanes = 0;
6074
6075         R_ResetViewRendering2D();
6076
6077         R_Bloom_CopyHDRTexture();
6078         R_Bloom_MakeTexture();
6079
6080         // restore the view settings
6081         r_waterstate.enabled = oldwaterstate;
6082         r_refdef.view.width = oldwidth;
6083         r_refdef.view.height = oldheight;
6084         r_refdef.view.colorscale = oldcolorscale;
6085
6086         R_ResetViewRendering3D();
6087
6088         R_ClearScreen(r_refdef.fogenabled);
6089         if (r_timereport_active)
6090                 R_TimeReport("viewclear");
6091 }
6092
6093 static void R_BlendView(void)
6094 {
6095         unsigned int permutation;
6096         float uservecs[4][4];
6097
6098         switch (vid.renderpath)
6099         {
6100         case RENDERPATH_GL20:
6101         case RENDERPATH_D3D9:
6102         case RENDERPATH_D3D10:
6103         case RENDERPATH_D3D11:
6104         case RENDERPATH_SOFT:
6105         case RENDERPATH_GLES2:
6106                 permutation =
6107                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6108                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6109                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6110                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6111                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6112
6113                 if (r_bloomstate.texture_screen)
6114                 {
6115                         // make sure the buffer is available
6116                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6117
6118                         R_ResetViewRendering2D();
6119                         R_Mesh_SetMainRenderTargets();
6120
6121                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6122                         {
6123                                 // declare variables
6124                                 float speed;
6125                                 static float avgspeed;
6126
6127                                 speed = VectorLength(cl.movement_velocity);
6128
6129                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6130                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6131
6132                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6133                                 speed = bound(0, speed, 1);
6134                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6135
6136                                 // calculate values into a standard alpha
6137                                 cl.motionbluralpha = 1 - exp(-
6138                                                 (
6139                                                  (r_motionblur.value * speed / 80)
6140                                                  +
6141                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6142                                                 )
6143                                                 /
6144                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6145                                            );
6146
6147                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6148                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6149                                 // apply the blur
6150                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6151                                 {
6152                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6153                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6154                                         switch(vid.renderpath)
6155                                         {
6156                                         case RENDERPATH_GL11:
6157                                         case RENDERPATH_GL13:
6158                                         case RENDERPATH_GL20:
6159                                         case RENDERPATH_SOFT:
6160                                         case RENDERPATH_GLES2:
6161                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6162                                                 break;
6163                                         case RENDERPATH_D3D9:
6164                                         case RENDERPATH_D3D10:
6165                                         case RENDERPATH_D3D11:
6166                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6167                                                 break;
6168                                         }
6169                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6170                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6171                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6172                                 }
6173                         }
6174
6175                         // copy view into the screen texture
6176                         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);
6177                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6178                 }
6179                 else if (!r_bloomstate.texture_bloom)
6180                 {
6181                         // we may still have to do view tint...
6182                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6183                         {
6184                                 // apply a color tint to the whole view
6185                                 R_ResetViewRendering2D();
6186                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6187                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6188                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6189                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6190                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6191                         }
6192                         break; // no screen processing, no bloom, skip it
6193                 }
6194
6195                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6196                 {
6197                         // render simple bloom effect
6198                         // copy the screen and shrink it and darken it for the bloom process
6199                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6200                         // make the bloom texture
6201                         R_Bloom_MakeTexture();
6202                 }
6203
6204 #if _MSC_VER >= 1400
6205 #define sscanf sscanf_s
6206 #endif
6207                 memset(uservecs, 0, sizeof(uservecs));
6208                 if (r_glsl_postprocess_uservec1_enable.integer)
6209                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6210                 if (r_glsl_postprocess_uservec2_enable.integer)
6211                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6212                 if (r_glsl_postprocess_uservec3_enable.integer)
6213                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6214                 if (r_glsl_postprocess_uservec4_enable.integer)
6215                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6216
6217                 R_ResetViewRendering2D();
6218                 GL_Color(1, 1, 1, 1);
6219                 GL_BlendFunc(GL_ONE, GL_ZERO);
6220
6221                 switch(vid.renderpath)
6222                 {
6223                 case RENDERPATH_GL20:
6224                 case RENDERPATH_GLES2:
6225                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6226                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6227                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6228                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6229                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6230                         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]);
6231                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6232                         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]);
6233                         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]);
6234                         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]);
6235                         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]);
6236                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6237                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6238                         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);
6239                         break;
6240                 case RENDERPATH_D3D9:
6241 #ifdef SUPPORTD3D
6242                         // 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...
6243                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6244                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6245                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6246                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6247                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6248                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6249                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6250                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6251                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6252                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6253                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6254                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6255                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6256                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6257 #endif
6258                         break;
6259                 case RENDERPATH_D3D10:
6260                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6261                         break;
6262                 case RENDERPATH_D3D11:
6263                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6264                         break;
6265                 case RENDERPATH_SOFT:
6266                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6267                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6268                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6269                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6270                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6271                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6272                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6273                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6274                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6275                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6276                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6277                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6278                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6279                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6280                         break;
6281                 default:
6282                         break;
6283                 }
6284                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6285                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6286                 break;
6287         case RENDERPATH_GL13:
6288         case RENDERPATH_GL11:
6289                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6290                 {
6291                         // apply a color tint to the whole view
6292                         R_ResetViewRendering2D();
6293                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6294                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6295                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6296                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6297                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6298                 }
6299                 break;
6300         }
6301 }
6302
6303 matrix4x4_t r_waterscrollmatrix;
6304
6305 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6306 {
6307         if (r_refdef.fog_density)
6308         {
6309                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6310                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6311                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6312
6313                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6314                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6315                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6316                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6317
6318                 {
6319                         vec3_t fogvec;
6320                         VectorCopy(r_refdef.fogcolor, fogvec);
6321                         //   color.rgb *= ContrastBoost * SceneBrightness;
6322                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6323                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6324                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6325                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6326                 }
6327         }
6328 }
6329
6330 void R_UpdateVariables(void)
6331 {
6332         R_Textures_Frame();
6333
6334         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6335
6336         r_refdef.farclip = r_farclip_base.value;
6337         if (r_refdef.scene.worldmodel)
6338                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6339         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6340
6341         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6342                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6343         r_refdef.polygonfactor = 0;
6344         r_refdef.polygonoffset = 0;
6345         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6346         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6347
6348         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6349         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6350         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6351         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6352         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6353         if (FAKELIGHT_ENABLED)
6354         {
6355                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6356         }
6357         if (r_showsurfaces.integer)
6358         {
6359                 r_refdef.scene.rtworld = false;
6360                 r_refdef.scene.rtworldshadows = false;
6361                 r_refdef.scene.rtdlight = false;
6362                 r_refdef.scene.rtdlightshadows = false;
6363                 r_refdef.lightmapintensity = 0;
6364         }
6365
6366         if (gamemode == GAME_NEHAHRA)
6367         {
6368                 if (gl_fogenable.integer)
6369                 {
6370                         r_refdef.oldgl_fogenable = true;
6371                         r_refdef.fog_density = gl_fogdensity.value;
6372                         r_refdef.fog_red = gl_fogred.value;
6373                         r_refdef.fog_green = gl_foggreen.value;
6374                         r_refdef.fog_blue = gl_fogblue.value;
6375                         r_refdef.fog_alpha = 1;
6376                         r_refdef.fog_start = 0;
6377                         r_refdef.fog_end = gl_skyclip.value;
6378                         r_refdef.fog_height = 1<<30;
6379                         r_refdef.fog_fadedepth = 128;
6380                 }
6381                 else if (r_refdef.oldgl_fogenable)
6382                 {
6383                         r_refdef.oldgl_fogenable = false;
6384                         r_refdef.fog_density = 0;
6385                         r_refdef.fog_red = 0;
6386                         r_refdef.fog_green = 0;
6387                         r_refdef.fog_blue = 0;
6388                         r_refdef.fog_alpha = 0;
6389                         r_refdef.fog_start = 0;
6390                         r_refdef.fog_end = 0;
6391                         r_refdef.fog_height = 1<<30;
6392                         r_refdef.fog_fadedepth = 128;
6393                 }
6394         }
6395
6396         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6397         r_refdef.fog_start = max(0, r_refdef.fog_start);
6398         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6399
6400         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6401
6402         if (r_refdef.fog_density && r_drawfog.integer)
6403         {
6404                 r_refdef.fogenabled = true;
6405                 // this is the point where the fog reaches 0.9986 alpha, which we
6406                 // consider a good enough cutoff point for the texture
6407                 // (0.9986 * 256 == 255.6)
6408                 if (r_fog_exp2.integer)
6409                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6410                 else
6411                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6412                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6413                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6414                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6415                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6416                         R_BuildFogHeightTexture();
6417                 // fog color was already set
6418                 // update the fog texture
6419                 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)
6420                         R_BuildFogTexture();
6421                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6422                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6423         }
6424         else
6425                 r_refdef.fogenabled = false;
6426
6427         switch(vid.renderpath)
6428         {
6429         case RENDERPATH_GL20:
6430         case RENDERPATH_D3D9:
6431         case RENDERPATH_D3D10:
6432         case RENDERPATH_D3D11:
6433         case RENDERPATH_SOFT:
6434         case RENDERPATH_GLES2:
6435                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6436                 {
6437                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6438                         {
6439                                 // build GLSL gamma texture
6440 #define RAMPWIDTH 256
6441                                 unsigned short ramp[RAMPWIDTH * 3];
6442                                 unsigned char rampbgr[RAMPWIDTH][4];
6443                                 int i;
6444
6445                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6446
6447                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6448                                 for(i = 0; i < RAMPWIDTH; ++i)
6449                                 {
6450                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6451                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6452                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6453                                         rampbgr[i][3] = 0;
6454                                 }
6455                                 if (r_texture_gammaramps)
6456                                 {
6457                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6458                                 }
6459                                 else
6460                                 {
6461                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6462                                 }
6463                         }
6464                 }
6465                 else
6466                 {
6467                         // remove GLSL gamma texture
6468                 }
6469                 break;
6470         case RENDERPATH_GL13:
6471         case RENDERPATH_GL11:
6472                 break;
6473         }
6474 }
6475
6476 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6477 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6478 /*
6479 ================
6480 R_SelectScene
6481 ================
6482 */
6483 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6484         if( scenetype != r_currentscenetype ) {
6485                 // store the old scenetype
6486                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6487                 r_currentscenetype = scenetype;
6488                 // move in the new scene
6489                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6490         }
6491 }
6492
6493 /*
6494 ================
6495 R_GetScenePointer
6496 ================
6497 */
6498 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6499 {
6500         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6501         if( scenetype == r_currentscenetype ) {
6502                 return &r_refdef.scene;
6503         } else {
6504                 return &r_scenes_store[ scenetype ];
6505         }
6506 }
6507
6508 /*
6509 ================
6510 R_RenderView
6511 ================
6512 */
6513 int dpsoftrast_test;
6514 void R_RenderView(void)
6515 {
6516         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6517
6518         dpsoftrast_test = r_test.integer;
6519
6520         if (r_timereport_active)
6521                 R_TimeReport("start");
6522         r_textureframe++; // used only by R_GetCurrentTexture
6523         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6524
6525         if(R_CompileShader_CheckStaticParms())
6526                 R_GLSL_Restart_f();
6527
6528         if (!r_drawentities.integer)
6529                 r_refdef.scene.numentities = 0;
6530
6531         R_AnimCache_ClearCache();
6532         R_FrameData_NewFrame();
6533
6534         /* adjust for stereo display */
6535         if(R_Stereo_Active())
6536         {
6537                 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);
6538                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6539         }
6540
6541         if (r_refdef.view.isoverlay)
6542         {
6543                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6544                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6545                 R_TimeReport("depthclear");
6546
6547                 r_refdef.view.showdebug = false;
6548
6549                 r_waterstate.enabled = false;
6550                 r_waterstate.numwaterplanes = 0;
6551
6552                 R_RenderScene();
6553
6554                 r_refdef.view.matrix = originalmatrix;
6555
6556                 CHECKGLERROR
6557                 return;
6558         }
6559
6560         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6561         {
6562                 r_refdef.view.matrix = originalmatrix;
6563                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6564         }
6565
6566         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6567
6568         R_RenderView_UpdateViewVectors();
6569
6570         R_Shadow_UpdateWorldLightSelection();
6571
6572         R_Bloom_StartFrame();
6573         R_Water_StartFrame();
6574
6575         CHECKGLERROR
6576         if (r_timereport_active)
6577                 R_TimeReport("viewsetup");
6578
6579         R_ResetViewRendering3D();
6580
6581         if (r_refdef.view.clear || r_refdef.fogenabled)
6582         {
6583                 R_ClearScreen(r_refdef.fogenabled);
6584                 if (r_timereport_active)
6585                         R_TimeReport("viewclear");
6586         }
6587         r_refdef.view.clear = true;
6588
6589         // this produces a bloom texture to be used in R_BlendView() later
6590         if (r_bloomstate.hdr)
6591         {
6592                 R_HDR_RenderBloomTexture();
6593                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6594                 r_textureframe++; // used only by R_GetCurrentTexture
6595         }
6596
6597         r_refdef.view.showdebug = true;
6598
6599         R_View_Update();
6600         if (r_timereport_active)
6601                 R_TimeReport("visibility");
6602
6603         r_waterstate.numwaterplanes = 0;
6604         if (r_waterstate.enabled)
6605                 R_RenderWaterPlanes();
6606
6607         R_RenderScene();
6608         r_waterstate.numwaterplanes = 0;
6609
6610         R_BlendView();
6611         if (r_timereport_active)
6612                 R_TimeReport("blendview");
6613
6614         GL_Scissor(0, 0, vid.width, vid.height);
6615         GL_ScissorTest(false);
6616
6617         r_refdef.view.matrix = originalmatrix;
6618
6619         CHECKGLERROR
6620 }
6621
6622 void R_RenderWaterPlanes(void)
6623 {
6624         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6625         {
6626                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6627                 if (r_timereport_active)
6628                         R_TimeReport("waterworld");
6629         }
6630
6631         // don't let sound skip if going slow
6632         if (r_refdef.scene.extraupdate)
6633                 S_ExtraUpdate ();
6634
6635         R_DrawModelsAddWaterPlanes();
6636         if (r_timereport_active)
6637                 R_TimeReport("watermodels");
6638
6639         if (r_waterstate.numwaterplanes)
6640         {
6641                 R_Water_ProcessPlanes();
6642                 if (r_timereport_active)
6643                         R_TimeReport("waterscenes");
6644         }
6645 }
6646
6647 extern void R_DrawLightningBeams (void);
6648 extern void VM_CL_AddPolygonsToMeshQueue (void);
6649 extern void R_DrawPortals (void);
6650 extern cvar_t cl_locs_show;
6651 static void R_DrawLocs(void);
6652 static void R_DrawEntityBBoxes(void);
6653 static void R_DrawModelDecals(void);
6654 extern void R_DrawModelShadows(void);
6655 extern void R_DrawModelShadowMaps(void);
6656 extern cvar_t cl_decals_newsystem;
6657 extern qboolean r_shadow_usingdeferredprepass;
6658 void R_RenderScene(void)
6659 {
6660         qboolean shadowmapping = false;
6661
6662         if (r_timereport_active)
6663                 R_TimeReport("beginscene");
6664
6665         r_refdef.stats.renders++;
6666
6667         R_UpdateFogColor();
6668
6669         // don't let sound skip if going slow
6670         if (r_refdef.scene.extraupdate)
6671                 S_ExtraUpdate ();
6672
6673         R_MeshQueue_BeginScene();
6674
6675         R_SkyStartFrame();
6676
6677         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);
6678
6679         if (r_timereport_active)
6680                 R_TimeReport("skystartframe");
6681
6682         if (cl.csqc_vidvars.drawworld)
6683         {
6684                 // don't let sound skip if going slow
6685                 if (r_refdef.scene.extraupdate)
6686                         S_ExtraUpdate ();
6687
6688                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6689                 {
6690                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6691                         if (r_timereport_active)
6692                                 R_TimeReport("worldsky");
6693                 }
6694
6695                 if (R_DrawBrushModelsSky() && r_timereport_active)
6696                         R_TimeReport("bmodelsky");
6697
6698                 if (skyrendermasked && skyrenderlater)
6699                 {
6700                         // we have to force off the water clipping plane while rendering sky
6701                         R_SetupView(false);
6702                         R_Sky();
6703                         R_SetupView(true);
6704                         if (r_timereport_active)
6705                                 R_TimeReport("sky");
6706                 }
6707         }
6708
6709         R_AnimCache_CacheVisibleEntities();
6710         if (r_timereport_active)
6711                 R_TimeReport("animation");
6712
6713         R_Shadow_PrepareLights();
6714         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6715                 R_Shadow_PrepareModelShadows();
6716         if (r_timereport_active)
6717                 R_TimeReport("preparelights");
6718
6719         if (R_Shadow_ShadowMappingEnabled())
6720                 shadowmapping = true;
6721
6722         if (r_shadow_usingdeferredprepass)
6723                 R_Shadow_DrawPrepass();
6724
6725         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6726         {
6727                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6728                 if (r_timereport_active)
6729                         R_TimeReport("worlddepth");
6730         }
6731         if (r_depthfirst.integer >= 2)
6732         {
6733                 R_DrawModelsDepth();
6734                 if (r_timereport_active)
6735                         R_TimeReport("modeldepth");
6736         }
6737
6738         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6739         {
6740                 R_DrawModelShadowMaps();
6741                 R_ResetViewRendering3D();
6742                 // don't let sound skip if going slow
6743                 if (r_refdef.scene.extraupdate)
6744                         S_ExtraUpdate ();
6745         }
6746
6747         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6748         {
6749                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6750                 if (r_timereport_active)
6751                         R_TimeReport("world");
6752         }
6753
6754         // don't let sound skip if going slow
6755         if (r_refdef.scene.extraupdate)
6756                 S_ExtraUpdate ();
6757
6758         R_DrawModels();
6759         if (r_timereport_active)
6760                 R_TimeReport("models");
6761
6762         // don't let sound skip if going slow
6763         if (r_refdef.scene.extraupdate)
6764                 S_ExtraUpdate ();
6765
6766         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6767         {
6768                 R_DrawModelShadows();
6769                 R_ResetViewRendering3D();
6770                 // don't let sound skip if going slow
6771                 if (r_refdef.scene.extraupdate)
6772                         S_ExtraUpdate ();
6773         }
6774
6775         if (!r_shadow_usingdeferredprepass)
6776         {
6777                 R_Shadow_DrawLights();
6778                 if (r_timereport_active)
6779                         R_TimeReport("rtlights");
6780         }
6781
6782         // don't let sound skip if going slow
6783         if (r_refdef.scene.extraupdate)
6784                 S_ExtraUpdate ();
6785
6786         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6787         {
6788                 R_DrawModelShadows();
6789                 R_ResetViewRendering3D();
6790                 // don't let sound skip if going slow
6791                 if (r_refdef.scene.extraupdate)
6792                         S_ExtraUpdate ();
6793         }
6794
6795         if (cl.csqc_vidvars.drawworld)
6796         {
6797                 if (cl_decals_newsystem.integer)
6798                 {
6799                         R_DrawModelDecals();
6800                         if (r_timereport_active)
6801                                 R_TimeReport("modeldecals");
6802                 }
6803                 else
6804                 {
6805                         R_DrawDecals();
6806                         if (r_timereport_active)
6807                                 R_TimeReport("decals");
6808                 }
6809
6810                 R_DrawParticles();
6811                 if (r_timereport_active)
6812                         R_TimeReport("particles");
6813
6814                 R_DrawExplosions();
6815                 if (r_timereport_active)
6816                         R_TimeReport("explosions");
6817
6818                 R_DrawLightningBeams();
6819                 if (r_timereport_active)
6820                         R_TimeReport("lightning");
6821         }
6822
6823         VM_CL_AddPolygonsToMeshQueue();
6824
6825         if (r_refdef.view.showdebug)
6826         {
6827                 if (cl_locs_show.integer)
6828                 {
6829                         R_DrawLocs();
6830                         if (r_timereport_active)
6831                                 R_TimeReport("showlocs");
6832                 }
6833
6834                 if (r_drawportals.integer)
6835                 {
6836                         R_DrawPortals();
6837                         if (r_timereport_active)
6838                                 R_TimeReport("portals");
6839                 }
6840
6841                 if (r_showbboxes.value > 0)
6842                 {
6843                         R_DrawEntityBBoxes();
6844                         if (r_timereport_active)
6845                                 R_TimeReport("bboxes");
6846                 }
6847         }
6848
6849         R_MeshQueue_RenderTransparent();
6850         if (r_timereport_active)
6851                 R_TimeReport("drawtrans");
6852
6853         if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0 || r_showoverdraw.value > 0))
6854         {
6855                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6856                 if (r_timereport_active)
6857                         R_TimeReport("worlddebug");
6858                 R_DrawModelsDebug();
6859                 if (r_timereport_active)
6860                         R_TimeReport("modeldebug");
6861         }
6862
6863         if (cl.csqc_vidvars.drawworld)
6864         {
6865                 R_Shadow_DrawCoronas();
6866                 if (r_timereport_active)
6867                         R_TimeReport("coronas");
6868         }
6869
6870 #if 0
6871         {
6872                 GL_DepthTest(false);
6873                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6874                 GL_Color(1, 1, 1, 1);
6875                 qglBegin(GL_POLYGON);
6876                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6877                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6878                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6879                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6880                 qglEnd();
6881                 qglBegin(GL_POLYGON);
6882                 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]);
6883                 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]);
6884                 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]);
6885                 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]);
6886                 qglEnd();
6887                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6888         }
6889 #endif
6890
6891         // don't let sound skip if going slow
6892         if (r_refdef.scene.extraupdate)
6893                 S_ExtraUpdate ();
6894
6895         R_ResetViewRendering2D();
6896 }
6897
6898 static const unsigned short bboxelements[36] =
6899 {
6900         5, 1, 3, 5, 3, 7,
6901         6, 2, 0, 6, 0, 4,
6902         7, 3, 2, 7, 2, 6,
6903         4, 0, 1, 4, 1, 5,
6904         4, 5, 7, 4, 7, 6,
6905         1, 0, 2, 1, 2, 3,
6906 };
6907
6908 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6909 {
6910         int i;
6911         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6912
6913         RSurf_ActiveWorldEntity();
6914
6915         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6916         GL_DepthMask(false);
6917         GL_DepthRange(0, 1);
6918         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6919 //      R_Mesh_ResetTextureState();
6920
6921         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6922         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6923         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6924         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6925         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6926         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6927         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6928         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6929         R_FillColors(color4f, 8, cr, cg, cb, ca);
6930         if (r_refdef.fogenabled)
6931         {
6932                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6933                 {
6934                         f1 = RSurf_FogVertex(v);
6935                         f2 = 1 - f1;
6936                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6937                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6938                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6939                 }
6940         }
6941         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6942         R_Mesh_ResetTextureState();
6943         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6944         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6945 }
6946
6947 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6948 {
6949         int i;
6950         float color[4];
6951         prvm_edict_t *edict;
6952         prvm_prog_t *prog_save = prog;
6953
6954         // this function draws bounding boxes of server entities
6955         if (!sv.active)
6956                 return;
6957
6958         GL_CullFace(GL_NONE);
6959         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6960
6961         prog = 0;
6962         SV_VM_Begin();
6963         for (i = 0;i < numsurfaces;i++)
6964         {
6965                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6966                 switch ((int)edict->fields.server->solid)
6967                 {
6968                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6969                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6970                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6971                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6972                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6973                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6974                 }
6975                 color[3] *= r_showbboxes.value;
6976                 color[3] = bound(0, color[3], 1);
6977                 GL_DepthTest(!r_showdisabledepthtest.integer);
6978                 GL_CullFace(r_refdef.view.cullface_front);
6979                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6980         }
6981         SV_VM_End();
6982         prog = prog_save;
6983 }
6984
6985 static void R_DrawEntityBBoxes(void)
6986 {
6987         int i;
6988         prvm_edict_t *edict;
6989         vec3_t center;
6990         prvm_prog_t *prog_save = prog;
6991
6992         // this function draws bounding boxes of server entities
6993         if (!sv.active)
6994                 return;
6995
6996         prog = 0;
6997         SV_VM_Begin();
6998         for (i = 0;i < prog->num_edicts;i++)
6999         {
7000                 edict = PRVM_EDICT_NUM(i);
7001                 if (edict->priv.server->free)
7002                         continue;
7003                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7004                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7005                         continue;
7006                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7007                         continue;
7008                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7009                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7010         }
7011         SV_VM_End();
7012         prog = prog_save;
7013 }
7014
7015 static const int nomodelelement3i[24] =
7016 {
7017         5, 2, 0,
7018         5, 1, 2,
7019         5, 0, 3,
7020         5, 3, 1,
7021         0, 2, 4,
7022         2, 1, 4,
7023         3, 0, 4,
7024         1, 3, 4
7025 };
7026
7027 static const unsigned short nomodelelement3s[24] =
7028 {
7029         5, 2, 0,
7030         5, 1, 2,
7031         5, 0, 3,
7032         5, 3, 1,
7033         0, 2, 4,
7034         2, 1, 4,
7035         3, 0, 4,
7036         1, 3, 4
7037 };
7038
7039 static const float nomodelvertex3f[6*3] =
7040 {
7041         -16,   0,   0,
7042          16,   0,   0,
7043           0, -16,   0,
7044           0,  16,   0,
7045           0,   0, -16,
7046           0,   0,  16
7047 };
7048
7049 static const float nomodelcolor4f[6*4] =
7050 {
7051         0.0f, 0.0f, 0.5f, 1.0f,
7052         0.0f, 0.0f, 0.5f, 1.0f,
7053         0.0f, 0.5f, 0.0f, 1.0f,
7054         0.0f, 0.5f, 0.0f, 1.0f,
7055         0.5f, 0.0f, 0.0f, 1.0f,
7056         0.5f, 0.0f, 0.0f, 1.0f
7057 };
7058
7059 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7060 {
7061         int i;
7062         float f1, f2, *c;
7063         float color4f[6*4];
7064
7065         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);
7066
7067         // this is only called once per entity so numsurfaces is always 1, and
7068         // surfacelist is always {0}, so this code does not handle batches
7069
7070         if (rsurface.ent_flags & RENDER_ADDITIVE)
7071         {
7072                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7073                 GL_DepthMask(false);
7074         }
7075         else if (rsurface.colormod[3] < 1)
7076         {
7077                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7078                 GL_DepthMask(false);
7079         }
7080         else
7081         {
7082                 GL_BlendFunc(GL_ONE, GL_ZERO);
7083                 GL_DepthMask(true);
7084         }
7085         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7086         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7087         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7088         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7089         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7090         for (i = 0, c = color4f;i < 6;i++, c += 4)
7091         {
7092                 c[0] *= rsurface.colormod[0];
7093                 c[1] *= rsurface.colormod[1];
7094                 c[2] *= rsurface.colormod[2];
7095                 c[3] *= rsurface.colormod[3];
7096         }
7097         if (r_refdef.fogenabled)
7098         {
7099                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7100                 {
7101                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7102                         f2 = 1 - f1;
7103                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7104                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7105                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7106                 }
7107         }
7108 //      R_Mesh_ResetTextureState();
7109         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7110         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7111         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7112 }
7113
7114 void R_DrawNoModel(entity_render_t *ent)
7115 {
7116         vec3_t org;
7117         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7118         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7119                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7120         else
7121                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7122 }
7123
7124 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7125 {
7126         vec3_t right1, right2, diff, normal;
7127
7128         VectorSubtract (org2, org1, normal);
7129
7130         // calculate 'right' vector for start
7131         VectorSubtract (r_refdef.view.origin, org1, diff);
7132         CrossProduct (normal, diff, right1);
7133         VectorNormalize (right1);
7134
7135         // calculate 'right' vector for end
7136         VectorSubtract (r_refdef.view.origin, org2, diff);
7137         CrossProduct (normal, diff, right2);
7138         VectorNormalize (right2);
7139
7140         vert[ 0] = org1[0] + width * right1[0];
7141         vert[ 1] = org1[1] + width * right1[1];
7142         vert[ 2] = org1[2] + width * right1[2];
7143         vert[ 3] = org1[0] - width * right1[0];
7144         vert[ 4] = org1[1] - width * right1[1];
7145         vert[ 5] = org1[2] - width * right1[2];
7146         vert[ 6] = org2[0] - width * right2[0];
7147         vert[ 7] = org2[1] - width * right2[1];
7148         vert[ 8] = org2[2] - width * right2[2];
7149         vert[ 9] = org2[0] + width * right2[0];
7150         vert[10] = org2[1] + width * right2[1];
7151         vert[11] = org2[2] + width * right2[2];
7152 }
7153
7154 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)
7155 {
7156         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7157         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7158         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7159         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7160         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7161         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7162         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7163         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7164         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7165         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7166         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7167         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7168 }
7169
7170 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7171 {
7172         int i;
7173         float *vertex3f;
7174         float v[3];
7175         VectorSet(v, x, y, z);
7176         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7177                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7178                         break;
7179         if (i == mesh->numvertices)
7180         {
7181                 if (mesh->numvertices < mesh->maxvertices)
7182                 {
7183                         VectorCopy(v, vertex3f);
7184                         mesh->numvertices++;
7185                 }
7186                 return mesh->numvertices;
7187         }
7188         else
7189                 return i;
7190 }
7191
7192 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7193 {
7194         int i;
7195         int *e, element[3];
7196         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7197         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7198         e = mesh->element3i + mesh->numtriangles * 3;
7199         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7200         {
7201                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7202                 if (mesh->numtriangles < mesh->maxtriangles)
7203                 {
7204                         *e++ = element[0];
7205                         *e++ = element[1];
7206                         *e++ = element[2];
7207                         mesh->numtriangles++;
7208                 }
7209                 element[1] = element[2];
7210         }
7211 }
7212
7213 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7214 {
7215         int i;
7216         int *e, element[3];
7217         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7218         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7219         e = mesh->element3i + mesh->numtriangles * 3;
7220         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7221         {
7222                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7223                 if (mesh->numtriangles < mesh->maxtriangles)
7224                 {
7225                         *e++ = element[0];
7226                         *e++ = element[1];
7227                         *e++ = element[2];
7228                         mesh->numtriangles++;
7229                 }
7230                 element[1] = element[2];
7231         }
7232 }
7233
7234 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7235 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7236 {
7237         int planenum, planenum2;
7238         int w;
7239         int tempnumpoints;
7240         mplane_t *plane, *plane2;
7241         double maxdist;
7242         double temppoints[2][256*3];
7243         // figure out how large a bounding box we need to properly compute this brush
7244         maxdist = 0;
7245         for (w = 0;w < numplanes;w++)
7246                 maxdist = max(maxdist, fabs(planes[w].dist));
7247         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7248         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7249         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7250         {
7251                 w = 0;
7252                 tempnumpoints = 4;
7253                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7254                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7255                 {
7256                         if (planenum2 == planenum)
7257                                 continue;
7258                         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);
7259                         w = !w;
7260                 }
7261                 if (tempnumpoints < 3)
7262                         continue;
7263                 // generate elements forming a triangle fan for this polygon
7264                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7265         }
7266 }
7267
7268 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)
7269 {
7270         texturelayer_t *layer;
7271         layer = t->currentlayers + t->currentnumlayers++;
7272         layer->type = type;
7273         layer->depthmask = depthmask;
7274         layer->blendfunc1 = blendfunc1;
7275         layer->blendfunc2 = blendfunc2;
7276         layer->texture = texture;
7277         layer->texmatrix = *matrix;
7278         layer->color[0] = r;
7279         layer->color[1] = g;
7280         layer->color[2] = b;
7281         layer->color[3] = a;
7282 }
7283
7284 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7285 {
7286         if(parms[0] == 0 && parms[1] == 0)
7287                 return false;
7288         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7289                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7290                         return false;
7291         return true;
7292 }
7293
7294 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7295 {
7296         double index, f;
7297         index = parms[2] + r_refdef.scene.time * parms[3];
7298         index -= floor(index);
7299         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7300         {
7301         default:
7302         case Q3WAVEFUNC_NONE:
7303         case Q3WAVEFUNC_NOISE:
7304         case Q3WAVEFUNC_COUNT:
7305                 f = 0;
7306                 break;
7307         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7308         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7309         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7310         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7311         case Q3WAVEFUNC_TRIANGLE:
7312                 index *= 4;
7313                 f = index - floor(index);
7314                 if (index < 1)
7315                         f = f;
7316                 else if (index < 2)
7317                         f = 1 - f;
7318                 else if (index < 3)
7319                         f = -f;
7320                 else
7321                         f = -(1 - f);
7322                 break;
7323         }
7324         f = parms[0] + parms[1] * f;
7325         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7326                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7327         return (float) f;
7328 }
7329
7330 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7331 {
7332         int w, h, idx;
7333         float f;
7334         float tcmat[12];
7335         matrix4x4_t matrix, temp;
7336         switch(tcmod->tcmod)
7337         {
7338                 case Q3TCMOD_COUNT:
7339                 case Q3TCMOD_NONE:
7340                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7341                                 matrix = r_waterscrollmatrix;
7342                         else
7343                                 matrix = identitymatrix;
7344                         break;
7345                 case Q3TCMOD_ENTITYTRANSLATE:
7346                         // this is used in Q3 to allow the gamecode to control texcoord
7347                         // scrolling on the entity, which is not supported in darkplaces yet.
7348                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7349                         break;
7350                 case Q3TCMOD_ROTATE:
7351                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7352                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7353                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7354                         break;
7355                 case Q3TCMOD_SCALE:
7356                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7357                         break;
7358                 case Q3TCMOD_SCROLL:
7359                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7360                         break;
7361                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7362                         w = (int) tcmod->parms[0];
7363                         h = (int) tcmod->parms[1];
7364                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7365                         f = f - floor(f);
7366                         idx = (int) floor(f * w * h);
7367                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7368                         break;
7369                 case Q3TCMOD_STRETCH:
7370                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7371                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7372                         break;
7373                 case Q3TCMOD_TRANSFORM:
7374                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7375                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7376                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7377                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7378                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7379                         break;
7380                 case Q3TCMOD_TURBULENT:
7381                         // this is handled in the RSurf_PrepareVertices function
7382                         matrix = identitymatrix;
7383                         break;
7384         }
7385         temp = *texmatrix;
7386         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7387 }
7388
7389 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7390 {
7391         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7392         char name[MAX_QPATH];
7393         skinframe_t *skinframe;
7394         unsigned char pixels[296*194];
7395         strlcpy(cache->name, skinname, sizeof(cache->name));
7396         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7397         if (developer_loading.integer)
7398                 Con_Printf("loading %s\n", name);
7399         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7400         if (!skinframe || !skinframe->base)
7401         {
7402                 unsigned char *f;
7403                 fs_offset_t filesize;
7404                 skinframe = NULL;
7405                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7406                 if (f)
7407                 {
7408                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7409                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7410                         Mem_Free(f);
7411                 }
7412         }
7413         cache->skinframe = skinframe;
7414 }
7415
7416 texture_t *R_GetCurrentTexture(texture_t *t)
7417 {
7418         int i;
7419         const entity_render_t *ent = rsurface.entity;
7420         dp_model_t *model = ent->model;
7421         q3shaderinfo_layer_tcmod_t *tcmod;
7422
7423         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7424                 return t->currentframe;
7425         t->update_lastrenderframe = r_textureframe;
7426         t->update_lastrenderentity = (void *)ent;
7427
7428         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7429                 t->camera_entity = ent->entitynumber;
7430         else
7431                 t->camera_entity = 0;
7432
7433         // switch to an alternate material if this is a q1bsp animated material
7434         {
7435                 texture_t *texture = t;
7436                 int s = rsurface.ent_skinnum;
7437                 if ((unsigned int)s >= (unsigned int)model->numskins)
7438                         s = 0;
7439                 if (model->skinscenes)
7440                 {
7441                         if (model->skinscenes[s].framecount > 1)
7442                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7443                         else
7444                                 s = model->skinscenes[s].firstframe;
7445                 }
7446                 if (s > 0)
7447                         t = t + s * model->num_surfaces;
7448                 if (t->animated)
7449                 {
7450                         // use an alternate animation if the entity's frame is not 0,
7451                         // and only if the texture has an alternate animation
7452                         if (rsurface.ent_alttextures && t->anim_total[1])
7453                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7454                         else
7455                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7456                 }
7457                 texture->currentframe = t;
7458         }
7459
7460         // update currentskinframe to be a qw skin or animation frame
7461         if (rsurface.ent_qwskin >= 0)
7462         {
7463                 i = rsurface.ent_qwskin;
7464                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7465                 {
7466                         r_qwskincache_size = cl.maxclients;
7467                         if (r_qwskincache)
7468                                 Mem_Free(r_qwskincache);
7469                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7470                 }
7471                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7472                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7473                 t->currentskinframe = r_qwskincache[i].skinframe;
7474                 if (t->currentskinframe == NULL)
7475                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7476         }
7477         else if (t->numskinframes >= 2)
7478                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7479         if (t->backgroundnumskinframes >= 2)
7480                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7481
7482         t->currentmaterialflags = t->basematerialflags;
7483         t->currentalpha = rsurface.colormod[3];
7484         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7485                 t->currentalpha *= r_wateralpha.value;
7486         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7487                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7488         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7489                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7490         if (!(rsurface.ent_flags & RENDER_LIGHT))
7491                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7492         else if (FAKELIGHT_ENABLED)
7493         {
7494                         // no modellight if using fakelight for the map
7495         }
7496         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7497         {
7498                 // pick a model lighting mode
7499                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7500                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7501                 else
7502                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7503         }
7504         if (rsurface.ent_flags & RENDER_ADDITIVE)
7505                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7506         else if (t->currentalpha < 1)
7507                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7508         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7509                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7510         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7511                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7512         if (t->backgroundnumskinframes)
7513                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7514         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7515         {
7516                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7517                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7518         }
7519         else
7520                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7521         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7522                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7523
7524         // there is no tcmod
7525         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7526         {
7527                 t->currenttexmatrix = r_waterscrollmatrix;
7528                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7529         }
7530         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7531         {
7532                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7533                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7534         }
7535
7536         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7537                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7538         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7539                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7540
7541         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7542         if (t->currentskinframe->qpixels)
7543                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7544         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7545         if (!t->basetexture)
7546                 t->basetexture = r_texture_notexture;
7547         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7548         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7549         t->nmaptexture = t->currentskinframe->nmap;
7550         if (!t->nmaptexture)
7551                 t->nmaptexture = r_texture_blanknormalmap;
7552         t->glosstexture = r_texture_black;
7553         t->glowtexture = t->currentskinframe->glow;
7554         t->fogtexture = t->currentskinframe->fog;
7555         t->reflectmasktexture = t->currentskinframe->reflect;
7556         if (t->backgroundnumskinframes)
7557         {
7558                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7559                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7560                 t->backgroundglosstexture = r_texture_black;
7561                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7562                 if (!t->backgroundnmaptexture)
7563                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7564         }
7565         else
7566         {
7567                 t->backgroundbasetexture = r_texture_white;
7568                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7569                 t->backgroundglosstexture = r_texture_black;
7570                 t->backgroundglowtexture = NULL;
7571         }
7572         t->specularpower = r_shadow_glossexponent.value;
7573         // TODO: store reference values for these in the texture?
7574         t->specularscale = 0;
7575         if (r_shadow_gloss.integer > 0)
7576         {
7577                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7578                 {
7579                         if (r_shadow_glossintensity.value > 0)
7580                         {
7581                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7582                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7583                                 t->specularscale = r_shadow_glossintensity.value;
7584                         }
7585                 }
7586                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7587                 {
7588                         t->glosstexture = r_texture_white;
7589                         t->backgroundglosstexture = r_texture_white;
7590                         t->specularscale = r_shadow_gloss2intensity.value;
7591                         t->specularpower = r_shadow_gloss2exponent.value;
7592                 }
7593         }
7594         t->specularscale *= t->specularscalemod;
7595         t->specularpower *= t->specularpowermod;
7596
7597         // lightmaps mode looks bad with dlights using actual texturing, so turn
7598         // off the colormap and glossmap, but leave the normalmap on as it still
7599         // accurately represents the shading involved
7600         if (gl_lightmaps.integer)
7601         {
7602                 t->basetexture = r_texture_grey128;
7603                 t->pantstexture = r_texture_black;
7604                 t->shirttexture = r_texture_black;
7605                 t->nmaptexture = r_texture_blanknormalmap;
7606                 t->glosstexture = r_texture_black;
7607                 t->glowtexture = NULL;
7608                 t->fogtexture = NULL;
7609                 t->reflectmasktexture = NULL;
7610                 t->backgroundbasetexture = NULL;
7611                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7612                 t->backgroundglosstexture = r_texture_black;
7613                 t->backgroundglowtexture = NULL;
7614                 t->specularscale = 0;
7615                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7616         }
7617
7618         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7619         VectorClear(t->dlightcolor);
7620         t->currentnumlayers = 0;
7621         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7622         {
7623                 int blendfunc1, blendfunc2;
7624                 qboolean depthmask;
7625                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7626                 {
7627                         blendfunc1 = GL_SRC_ALPHA;
7628                         blendfunc2 = GL_ONE;
7629                 }
7630                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7631                 {
7632                         blendfunc1 = GL_SRC_ALPHA;
7633                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7634                 }
7635                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7636                 {
7637                         blendfunc1 = t->customblendfunc[0];
7638                         blendfunc2 = t->customblendfunc[1];
7639                 }
7640                 else
7641                 {
7642                         blendfunc1 = GL_ONE;
7643                         blendfunc2 = GL_ZERO;
7644                 }
7645                 // don't colormod evilblend textures
7646                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7647                         VectorSet(t->lightmapcolor, 1, 1, 1);
7648                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7649                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7650                 {
7651                         // fullbright is not affected by r_refdef.lightmapintensity
7652                         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]);
7653                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7654                                 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]);
7655                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7656                                 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]);
7657                 }
7658                 else
7659                 {
7660                         vec3_t ambientcolor;
7661                         float colorscale;
7662                         // set the color tint used for lights affecting this surface
7663                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7664                         colorscale = 2;
7665                         // q3bsp has no lightmap updates, so the lightstylevalue that
7666                         // would normally be baked into the lightmap must be
7667                         // applied to the color
7668                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7669                         if (model->type == mod_brushq3)
7670                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7671                         colorscale *= r_refdef.lightmapintensity;
7672                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7673                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7674                         // basic lit geometry
7675                         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]);
7676                         // add pants/shirt if needed
7677                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7678                                 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]);
7679                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7680                                 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]);
7681                         // now add ambient passes if needed
7682                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7683                         {
7684                                 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]);
7685                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7686                                         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]);
7687                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7688                                         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]);
7689                         }
7690                 }
7691                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7692                         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]);
7693                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7694                 {
7695                         // if this is opaque use alpha blend which will darken the earlier
7696                         // passes cheaply.
7697                         //
7698                         // if this is an alpha blended material, all the earlier passes
7699                         // were darkened by fog already, so we only need to add the fog
7700                         // color ontop through the fog mask texture
7701                         //
7702                         // if this is an additive blended material, all the earlier passes
7703                         // were darkened by fog already, and we should not add fog color
7704                         // (because the background was not darkened, there is no fog color
7705                         // that was lost behind it).
7706                         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]);
7707                 }
7708         }
7709
7710         return t->currentframe;
7711 }
7712
7713 rsurfacestate_t rsurface;
7714
7715 void RSurf_ActiveWorldEntity(void)
7716 {
7717         dp_model_t *model = r_refdef.scene.worldmodel;
7718         //if (rsurface.entity == r_refdef.scene.worldentity)
7719         //      return;
7720         rsurface.entity = r_refdef.scene.worldentity;
7721         rsurface.skeleton = NULL;
7722         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7723         rsurface.ent_skinnum = 0;
7724         rsurface.ent_qwskin = -1;
7725         rsurface.ent_shadertime = 0;
7726         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7727         rsurface.matrix = identitymatrix;
7728         rsurface.inversematrix = identitymatrix;
7729         rsurface.matrixscale = 1;
7730         rsurface.inversematrixscale = 1;
7731         R_EntityMatrix(&identitymatrix);
7732         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7733         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7734         rsurface.fograngerecip = r_refdef.fograngerecip;
7735         rsurface.fogheightfade = r_refdef.fogheightfade;
7736         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7737         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7738         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7739         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7740         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7741         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7742         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7743         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7744         rsurface.colormod[3] = 1;
7745         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);
7746         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7747         rsurface.frameblend[0].lerp = 1;
7748         rsurface.ent_alttextures = false;
7749         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7750         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7751         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7752         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7753         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7754         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7755         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7756         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7757         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7758         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7759         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7760         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7761         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7762         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7763         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7764         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7765         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7766         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7767         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7768         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7769         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7770         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7771         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7772         rsurface.modelelement3i = model->surfmesh.data_element3i;
7773         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7774         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7775         rsurface.modelelement3s = model->surfmesh.data_element3s;
7776         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7777         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7778         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7779         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7780         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7781         rsurface.modelsurfaces = model->data_surfaces;
7782         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7783         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7784         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7785         rsurface.modelgeneratedvertex = false;
7786         rsurface.batchgeneratedvertex = false;
7787         rsurface.batchfirstvertex = 0;
7788         rsurface.batchnumvertices = 0;
7789         rsurface.batchfirsttriangle = 0;
7790         rsurface.batchnumtriangles = 0;
7791         rsurface.batchvertex3f  = NULL;
7792         rsurface.batchvertex3f_vertexbuffer = NULL;
7793         rsurface.batchvertex3f_bufferoffset = 0;
7794         rsurface.batchsvector3f = NULL;
7795         rsurface.batchsvector3f_vertexbuffer = NULL;
7796         rsurface.batchsvector3f_bufferoffset = 0;
7797         rsurface.batchtvector3f = NULL;
7798         rsurface.batchtvector3f_vertexbuffer = NULL;
7799         rsurface.batchtvector3f_bufferoffset = 0;
7800         rsurface.batchnormal3f  = NULL;
7801         rsurface.batchnormal3f_vertexbuffer = NULL;
7802         rsurface.batchnormal3f_bufferoffset = 0;
7803         rsurface.batchlightmapcolor4f = NULL;
7804         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7805         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7806         rsurface.batchtexcoordtexture2f = NULL;
7807         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7808         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7809         rsurface.batchtexcoordlightmap2f = NULL;
7810         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7811         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7812         rsurface.batchvertexmesh = NULL;
7813         rsurface.batchvertexmeshbuffer = NULL;
7814         rsurface.batchvertex3fbuffer = NULL;
7815         rsurface.batchelement3i = NULL;
7816         rsurface.batchelement3i_indexbuffer = NULL;
7817         rsurface.batchelement3i_bufferoffset = 0;
7818         rsurface.batchelement3s = NULL;
7819         rsurface.batchelement3s_indexbuffer = NULL;
7820         rsurface.batchelement3s_bufferoffset = 0;
7821         rsurface.passcolor4f = NULL;
7822         rsurface.passcolor4f_vertexbuffer = NULL;
7823         rsurface.passcolor4f_bufferoffset = 0;
7824 }
7825
7826 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7827 {
7828         dp_model_t *model = ent->model;
7829         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7830         //      return;
7831         rsurface.entity = (entity_render_t *)ent;
7832         rsurface.skeleton = ent->skeleton;
7833         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7834         rsurface.ent_skinnum = ent->skinnum;
7835         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;
7836         rsurface.ent_shadertime = ent->shadertime;
7837         rsurface.ent_flags = ent->flags;
7838         rsurface.matrix = ent->matrix;
7839         rsurface.inversematrix = ent->inversematrix;
7840         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7841         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7842         R_EntityMatrix(&rsurface.matrix);
7843         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7844         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7845         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7846         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7847         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7848         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7849         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7850         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7851         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7852         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7853         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7854         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7855         rsurface.colormod[3] = ent->alpha;
7856         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7857         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7858         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7859         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7860         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7861         if (ent->model->brush.submodel && !prepass)
7862         {
7863                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7864                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7865         }
7866         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7867         {
7868                 if (ent->animcache_vertex3f)
7869                 {
7870                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7871                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7872                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7873                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7874                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7875                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7876                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7877                 }
7878                 else if (wanttangents)
7879                 {
7880                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7881                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7882                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7883                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7884                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7885                         rsurface.modelvertexmesh = NULL;
7886                         rsurface.modelvertexmeshbuffer = NULL;
7887                         rsurface.modelvertex3fbuffer = NULL;
7888                 }
7889                 else if (wantnormals)
7890                 {
7891                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7892                         rsurface.modelsvector3f = NULL;
7893                         rsurface.modeltvector3f = NULL;
7894                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7895                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7896                         rsurface.modelvertexmesh = NULL;
7897                         rsurface.modelvertexmeshbuffer = NULL;
7898                         rsurface.modelvertex3fbuffer = NULL;
7899                 }
7900                 else
7901                 {
7902                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7903                         rsurface.modelsvector3f = NULL;
7904                         rsurface.modeltvector3f = NULL;
7905                         rsurface.modelnormal3f = NULL;
7906                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7907                         rsurface.modelvertexmesh = NULL;
7908                         rsurface.modelvertexmeshbuffer = NULL;
7909                         rsurface.modelvertex3fbuffer = NULL;
7910                 }
7911                 rsurface.modelvertex3f_vertexbuffer = 0;
7912                 rsurface.modelvertex3f_bufferoffset = 0;
7913                 rsurface.modelsvector3f_vertexbuffer = 0;
7914                 rsurface.modelsvector3f_bufferoffset = 0;
7915                 rsurface.modeltvector3f_vertexbuffer = 0;
7916                 rsurface.modeltvector3f_bufferoffset = 0;
7917                 rsurface.modelnormal3f_vertexbuffer = 0;
7918                 rsurface.modelnormal3f_bufferoffset = 0;
7919                 rsurface.modelgeneratedvertex = true;
7920         }
7921         else
7922         {
7923                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7924                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7925                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7926                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7927                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7928                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7929                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7930                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7931                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7932                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7933                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7934                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7935                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7936                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7937                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7938                 rsurface.modelgeneratedvertex = false;
7939         }
7940         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7941         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7942         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7943         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7944         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7945         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7946         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7947         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7948         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7949         rsurface.modelelement3i = model->surfmesh.data_element3i;
7950         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7951         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7952         rsurface.modelelement3s = model->surfmesh.data_element3s;
7953         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7954         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7955         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7956         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7957         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7958         rsurface.modelsurfaces = model->data_surfaces;
7959         rsurface.batchgeneratedvertex = false;
7960         rsurface.batchfirstvertex = 0;
7961         rsurface.batchnumvertices = 0;
7962         rsurface.batchfirsttriangle = 0;
7963         rsurface.batchnumtriangles = 0;
7964         rsurface.batchvertex3f  = NULL;
7965         rsurface.batchvertex3f_vertexbuffer = NULL;
7966         rsurface.batchvertex3f_bufferoffset = 0;
7967         rsurface.batchsvector3f = NULL;
7968         rsurface.batchsvector3f_vertexbuffer = NULL;
7969         rsurface.batchsvector3f_bufferoffset = 0;
7970         rsurface.batchtvector3f = NULL;
7971         rsurface.batchtvector3f_vertexbuffer = NULL;
7972         rsurface.batchtvector3f_bufferoffset = 0;
7973         rsurface.batchnormal3f  = NULL;
7974         rsurface.batchnormal3f_vertexbuffer = NULL;
7975         rsurface.batchnormal3f_bufferoffset = 0;
7976         rsurface.batchlightmapcolor4f = NULL;
7977         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7978         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7979         rsurface.batchtexcoordtexture2f = NULL;
7980         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7981         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7982         rsurface.batchtexcoordlightmap2f = NULL;
7983         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7984         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7985         rsurface.batchvertexmesh = NULL;
7986         rsurface.batchvertexmeshbuffer = NULL;
7987         rsurface.batchvertex3fbuffer = NULL;
7988         rsurface.batchelement3i = NULL;
7989         rsurface.batchelement3i_indexbuffer = NULL;
7990         rsurface.batchelement3i_bufferoffset = 0;
7991         rsurface.batchelement3s = NULL;
7992         rsurface.batchelement3s_indexbuffer = NULL;
7993         rsurface.batchelement3s_bufferoffset = 0;
7994         rsurface.passcolor4f = NULL;
7995         rsurface.passcolor4f_vertexbuffer = NULL;
7996         rsurface.passcolor4f_bufferoffset = 0;
7997 }
7998
7999 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)
8000 {
8001         rsurface.entity = r_refdef.scene.worldentity;
8002         rsurface.skeleton = NULL;
8003         rsurface.ent_skinnum = 0;
8004         rsurface.ent_qwskin = -1;
8005         rsurface.ent_shadertime = shadertime;
8006         rsurface.ent_flags = entflags;
8007         rsurface.modelnumvertices = numvertices;
8008         rsurface.modelnumtriangles = numtriangles;
8009         rsurface.matrix = *matrix;
8010         rsurface.inversematrix = *inversematrix;
8011         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8012         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8013         R_EntityMatrix(&rsurface.matrix);
8014         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8015         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8016         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8017         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8018         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8019         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8020         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8021         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8022         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8023         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8024         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8025         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8026         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);
8027         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8028         rsurface.frameblend[0].lerp = 1;
8029         rsurface.ent_alttextures = false;
8030         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8031         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8032         if (wanttangents)
8033         {
8034                 rsurface.modelvertex3f = (float *)vertex3f;
8035                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8036                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8037                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8038         }
8039         else if (wantnormals)
8040         {
8041                 rsurface.modelvertex3f = (float *)vertex3f;
8042                 rsurface.modelsvector3f = NULL;
8043                 rsurface.modeltvector3f = NULL;
8044                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8045         }
8046         else
8047         {
8048                 rsurface.modelvertex3f = (float *)vertex3f;
8049                 rsurface.modelsvector3f = NULL;
8050                 rsurface.modeltvector3f = NULL;
8051                 rsurface.modelnormal3f = NULL;
8052         }
8053         rsurface.modelvertexmesh = NULL;
8054         rsurface.modelvertexmeshbuffer = NULL;
8055         rsurface.modelvertex3fbuffer = NULL;
8056         rsurface.modelvertex3f_vertexbuffer = 0;
8057         rsurface.modelvertex3f_bufferoffset = 0;
8058         rsurface.modelsvector3f_vertexbuffer = 0;
8059         rsurface.modelsvector3f_bufferoffset = 0;
8060         rsurface.modeltvector3f_vertexbuffer = 0;
8061         rsurface.modeltvector3f_bufferoffset = 0;
8062         rsurface.modelnormal3f_vertexbuffer = 0;
8063         rsurface.modelnormal3f_bufferoffset = 0;
8064         rsurface.modelgeneratedvertex = true;
8065         rsurface.modellightmapcolor4f  = (float *)color4f;
8066         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8067         rsurface.modellightmapcolor4f_bufferoffset = 0;
8068         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8069         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8070         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8071         rsurface.modeltexcoordlightmap2f  = NULL;
8072         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8073         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8074         rsurface.modelelement3i = (int *)element3i;
8075         rsurface.modelelement3i_indexbuffer = NULL;
8076         rsurface.modelelement3i_bufferoffset = 0;
8077         rsurface.modelelement3s = (unsigned short *)element3s;
8078         rsurface.modelelement3s_indexbuffer = NULL;
8079         rsurface.modelelement3s_bufferoffset = 0;
8080         rsurface.modellightmapoffsets = NULL;
8081         rsurface.modelsurfaces = NULL;
8082         rsurface.batchgeneratedvertex = false;
8083         rsurface.batchfirstvertex = 0;
8084         rsurface.batchnumvertices = 0;
8085         rsurface.batchfirsttriangle = 0;
8086         rsurface.batchnumtriangles = 0;
8087         rsurface.batchvertex3f  = NULL;
8088         rsurface.batchvertex3f_vertexbuffer = NULL;
8089         rsurface.batchvertex3f_bufferoffset = 0;
8090         rsurface.batchsvector3f = NULL;
8091         rsurface.batchsvector3f_vertexbuffer = NULL;
8092         rsurface.batchsvector3f_bufferoffset = 0;
8093         rsurface.batchtvector3f = NULL;
8094         rsurface.batchtvector3f_vertexbuffer = NULL;
8095         rsurface.batchtvector3f_bufferoffset = 0;
8096         rsurface.batchnormal3f  = NULL;
8097         rsurface.batchnormal3f_vertexbuffer = NULL;
8098         rsurface.batchnormal3f_bufferoffset = 0;
8099         rsurface.batchlightmapcolor4f = NULL;
8100         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8101         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8102         rsurface.batchtexcoordtexture2f = NULL;
8103         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8104         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8105         rsurface.batchtexcoordlightmap2f = NULL;
8106         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8107         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8108         rsurface.batchvertexmesh = NULL;
8109         rsurface.batchvertexmeshbuffer = NULL;
8110         rsurface.batchvertex3fbuffer = NULL;
8111         rsurface.batchelement3i = NULL;
8112         rsurface.batchelement3i_indexbuffer = NULL;
8113         rsurface.batchelement3i_bufferoffset = 0;
8114         rsurface.batchelement3s = NULL;
8115         rsurface.batchelement3s_indexbuffer = NULL;
8116         rsurface.batchelement3s_bufferoffset = 0;
8117         rsurface.passcolor4f = NULL;
8118         rsurface.passcolor4f_vertexbuffer = NULL;
8119         rsurface.passcolor4f_bufferoffset = 0;
8120
8121         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8122         {
8123                 if ((wantnormals || wanttangents) && !normal3f)
8124                 {
8125                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8126                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8127                 }
8128                 if (wanttangents && !svector3f)
8129                 {
8130                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8131                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8132                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8133                 }
8134         }
8135 }
8136
8137 float RSurf_FogPoint(const float *v)
8138 {
8139         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8140         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8141         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8142         float FogHeightFade = r_refdef.fogheightfade;
8143         float fogfrac;
8144         unsigned int fogmasktableindex;
8145         if (r_refdef.fogplaneviewabove)
8146                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8147         else
8148                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8149         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8150         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8151 }
8152
8153 float RSurf_FogVertex(const float *v)
8154 {
8155         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8156         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8157         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8158         float FogHeightFade = rsurface.fogheightfade;
8159         float fogfrac;
8160         unsigned int fogmasktableindex;
8161         if (r_refdef.fogplaneviewabove)
8162                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8163         else
8164                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8165         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8166         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8167 }
8168
8169 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8170 {
8171         int i;
8172         for (i = 0;i < numelements;i++)
8173                 outelement3i[i] = inelement3i[i] + adjust;
8174 }
8175
8176 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8177 extern cvar_t gl_vbo;
8178 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8179 {
8180         int deformindex;
8181         int firsttriangle;
8182         int numtriangles;
8183         int firstvertex;
8184         int endvertex;
8185         int numvertices;
8186         int surfacefirsttriangle;
8187         int surfacenumtriangles;
8188         int surfacefirstvertex;
8189         int surfaceendvertex;
8190         int surfacenumvertices;
8191         int batchnumvertices;
8192         int batchnumtriangles;
8193         int needsupdate;
8194         int i, j;
8195         qboolean gaps;
8196         qboolean dynamicvertex;
8197         float amplitude;
8198         float animpos;
8199         float scale;
8200         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8201         float waveparms[4];
8202         q3shaderinfo_deform_t *deform;
8203         const msurface_t *surface, *firstsurface;
8204         r_vertexmesh_t *vertexmesh;
8205         if (!texturenumsurfaces)
8206                 return;
8207         // find vertex range of this surface batch
8208         gaps = false;
8209         firstsurface = texturesurfacelist[0];
8210         firsttriangle = firstsurface->num_firsttriangle;
8211         batchnumvertices = 0;
8212         batchnumtriangles = 0;
8213         firstvertex = endvertex = firstsurface->num_firstvertex;
8214         for (i = 0;i < texturenumsurfaces;i++)
8215         {
8216                 surface = texturesurfacelist[i];
8217                 if (surface != firstsurface + i)
8218                         gaps = true;
8219                 surfacefirstvertex = surface->num_firstvertex;
8220                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8221                 surfacenumvertices = surface->num_vertices;
8222                 surfacenumtriangles = surface->num_triangles;
8223                 if (firstvertex > surfacefirstvertex)
8224                         firstvertex = surfacefirstvertex;
8225                 if (endvertex < surfaceendvertex)
8226                         endvertex = surfaceendvertex;
8227                 batchnumvertices += surfacenumvertices;
8228                 batchnumtriangles += surfacenumtriangles;
8229         }
8230
8231         // we now know the vertex range used, and if there are any gaps in it
8232         rsurface.batchfirstvertex = firstvertex;
8233         rsurface.batchnumvertices = endvertex - firstvertex;
8234         rsurface.batchfirsttriangle = firsttriangle;
8235         rsurface.batchnumtriangles = batchnumtriangles;
8236
8237         // this variable holds flags for which properties have been updated that
8238         // may require regenerating vertexmesh array...
8239         needsupdate = 0;
8240
8241         // check if any dynamic vertex processing must occur
8242         dynamicvertex = false;
8243
8244         // if there is a chance of animated vertex colors, it's a dynamic batch
8245         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8246         {
8247                 dynamicvertex = true;
8248                 batchneed |= BATCHNEED_NOGAPS;
8249                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8250         }
8251
8252         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8253         {
8254                 switch (deform->deform)
8255                 {
8256                 default:
8257                 case Q3DEFORM_PROJECTIONSHADOW:
8258                 case Q3DEFORM_TEXT0:
8259                 case Q3DEFORM_TEXT1:
8260                 case Q3DEFORM_TEXT2:
8261                 case Q3DEFORM_TEXT3:
8262                 case Q3DEFORM_TEXT4:
8263                 case Q3DEFORM_TEXT5:
8264                 case Q3DEFORM_TEXT6:
8265                 case Q3DEFORM_TEXT7:
8266                 case Q3DEFORM_NONE:
8267                         break;
8268                 case Q3DEFORM_AUTOSPRITE:
8269                         dynamicvertex = true;
8270                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8271                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8272                         break;
8273                 case Q3DEFORM_AUTOSPRITE2:
8274                         dynamicvertex = true;
8275                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8276                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8277                         break;
8278                 case Q3DEFORM_NORMAL:
8279                         dynamicvertex = true;
8280                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8281                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8282                         break;
8283                 case Q3DEFORM_WAVE:
8284                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8285                                 break; // if wavefunc is a nop, ignore this transform
8286                         dynamicvertex = true;
8287                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8288                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8289                         break;
8290                 case Q3DEFORM_BULGE:
8291                         dynamicvertex = true;
8292                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8293                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8294                         break;
8295                 case Q3DEFORM_MOVE:
8296                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8297                                 break; // if wavefunc is a nop, ignore this transform
8298                         dynamicvertex = true;
8299                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8300                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8301                         break;
8302                 }
8303         }
8304         switch(rsurface.texture->tcgen.tcgen)
8305         {
8306         default:
8307         case Q3TCGEN_TEXTURE:
8308                 break;
8309         case Q3TCGEN_LIGHTMAP:
8310                 dynamicvertex = true;
8311                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8312                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8313                 break;
8314         case Q3TCGEN_VECTOR:
8315                 dynamicvertex = true;
8316                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8317                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8318                 break;
8319         case Q3TCGEN_ENVIRONMENT:
8320                 dynamicvertex = true;
8321                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8322                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8323                 break;
8324         }
8325         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8326         {
8327                 dynamicvertex = true;
8328                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8329                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8330         }
8331
8332         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8333         {
8334                 dynamicvertex = true;
8335                 batchneed |= BATCHNEED_NOGAPS;
8336                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8337         }
8338
8339         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8340         {
8341                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8342                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8343                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8344                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8345                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8346                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8347                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8348         }
8349
8350         // when the model data has no vertex buffer (dynamic mesh), we need to
8351         // eliminate gaps
8352         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8353                 batchneed |= BATCHNEED_NOGAPS;
8354
8355         // if needsupdate, we have to do a dynamic vertex batch for sure
8356         if (needsupdate & batchneed)
8357                 dynamicvertex = true;
8358
8359         // see if we need to build vertexmesh from arrays
8360         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8361                 dynamicvertex = true;
8362
8363         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8364         // also some drivers strongly dislike firstvertex
8365         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8366                 dynamicvertex = true;
8367
8368         rsurface.batchvertex3f = rsurface.modelvertex3f;
8369         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8370         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8371         rsurface.batchsvector3f = rsurface.modelsvector3f;
8372         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8373         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8374         rsurface.batchtvector3f = rsurface.modeltvector3f;
8375         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8376         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8377         rsurface.batchnormal3f = rsurface.modelnormal3f;
8378         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8379         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8380         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8381         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8382         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8383         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8384         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8385         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8386         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8387         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8388         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8389         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8390         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8391         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8392         rsurface.batchelement3i = rsurface.modelelement3i;
8393         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8394         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8395         rsurface.batchelement3s = rsurface.modelelement3s;
8396         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8397         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8398
8399         // if any dynamic vertex processing has to occur in software, we copy the
8400         // entire surface list together before processing to rebase the vertices
8401         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8402         //
8403         // if any gaps exist and we do not have a static vertex buffer, we have to
8404         // copy the surface list together to avoid wasting upload bandwidth on the
8405         // vertices in the gaps.
8406         //
8407         // if gaps exist and we have a static vertex buffer, we still have to
8408         // combine the index buffer ranges into one dynamic index buffer.
8409         //
8410         // in all cases we end up with data that can be drawn in one call.
8411
8412         if (!dynamicvertex)
8413         {
8414                 // static vertex data, just set pointers...
8415                 rsurface.batchgeneratedvertex = false;
8416                 // if there are gaps, we want to build a combined index buffer,
8417                 // otherwise use the original static buffer with an appropriate offset
8418                 if (gaps)
8419                 {
8420                         // build a new triangle elements array for this batch
8421                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8422                         rsurface.batchfirsttriangle = 0;
8423                         numtriangles = 0;
8424                         for (i = 0;i < texturenumsurfaces;i++)
8425                         {
8426                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8427                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8428                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8429                                 numtriangles += surfacenumtriangles;
8430                         }
8431                         rsurface.batchelement3i_indexbuffer = NULL;
8432                         rsurface.batchelement3i_bufferoffset = 0;
8433                         rsurface.batchelement3s = NULL;
8434                         rsurface.batchelement3s_indexbuffer = NULL;
8435                         rsurface.batchelement3s_bufferoffset = 0;
8436                         if (endvertex <= 65536)
8437                         {
8438                                 // make a 16bit (unsigned short) index array if possible
8439                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8440                                 for (i = 0;i < numtriangles*3;i++)
8441                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8442                         }
8443                 }
8444                 return;
8445         }
8446
8447         // something needs software processing, do it for real...
8448         // we only directly handle separate array data in this case and then
8449         // generate interleaved data if needed...
8450         rsurface.batchgeneratedvertex = true;
8451
8452         // now copy the vertex data into a combined array and make an index array
8453         // (this is what Quake3 does all the time)
8454         //if (gaps || rsurface.batchfirstvertex)
8455         {
8456                 rsurface.batchvertex3fbuffer = NULL;
8457                 rsurface.batchvertexmesh = NULL;
8458                 rsurface.batchvertexmeshbuffer = NULL;
8459                 rsurface.batchvertex3f = NULL;
8460                 rsurface.batchvertex3f_vertexbuffer = NULL;
8461                 rsurface.batchvertex3f_bufferoffset = 0;
8462                 rsurface.batchsvector3f = NULL;
8463                 rsurface.batchsvector3f_vertexbuffer = NULL;
8464                 rsurface.batchsvector3f_bufferoffset = 0;
8465                 rsurface.batchtvector3f = NULL;
8466                 rsurface.batchtvector3f_vertexbuffer = NULL;
8467                 rsurface.batchtvector3f_bufferoffset = 0;
8468                 rsurface.batchnormal3f = NULL;
8469                 rsurface.batchnormal3f_vertexbuffer = NULL;
8470                 rsurface.batchnormal3f_bufferoffset = 0;
8471                 rsurface.batchlightmapcolor4f = NULL;
8472                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8473                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8474                 rsurface.batchtexcoordtexture2f = NULL;
8475                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8476                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8477                 rsurface.batchtexcoordlightmap2f = NULL;
8478                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8479                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8480                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8481                 rsurface.batchelement3i_indexbuffer = NULL;
8482                 rsurface.batchelement3i_bufferoffset = 0;
8483                 rsurface.batchelement3s = NULL;
8484                 rsurface.batchelement3s_indexbuffer = NULL;
8485                 rsurface.batchelement3s_bufferoffset = 0;
8486                 // we'll only be setting up certain arrays as needed
8487                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8488                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8489                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8490                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8491                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8492                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8493                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8494                 {
8495                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8496                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8497                 }
8498                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8499                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8500                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8501                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8502                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8503                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8504                 numvertices = 0;
8505                 numtriangles = 0;
8506                 for (i = 0;i < texturenumsurfaces;i++)
8507                 {
8508                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8509                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8510                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8511                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8512                         // copy only the data requested
8513                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8514                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8515                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8516                         {
8517                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8518                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8519                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8520                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8521                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8522                                 {
8523                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8524                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8525                                 }
8526                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8527                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8528                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8529                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8530                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8531                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8532                         }
8533                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8534                         numvertices += surfacenumvertices;
8535                         numtriangles += surfacenumtriangles;
8536                 }
8537
8538                 // generate a 16bit index array as well if possible
8539                 // (in general, dynamic batches fit)
8540                 if (numvertices <= 65536)
8541                 {
8542                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8543                         for (i = 0;i < numtriangles*3;i++)
8544                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8545                 }
8546
8547                 // since we've copied everything, the batch now starts at 0
8548                 rsurface.batchfirstvertex = 0;
8549                 rsurface.batchnumvertices = batchnumvertices;
8550                 rsurface.batchfirsttriangle = 0;
8551                 rsurface.batchnumtriangles = batchnumtriangles;
8552         }
8553
8554         // q1bsp surfaces rendered in vertex color mode have to have colors
8555         // calculated based on lightstyles
8556         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8557         {
8558                 // generate color arrays for the surfaces in this list
8559                 int c[4];
8560                 int scale;
8561                 int size3;
8562                 const int *offsets;
8563                 const unsigned char *lm;
8564                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8565                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8566                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8567                 numvertices = 0;
8568                 for (i = 0;i < texturenumsurfaces;i++)
8569                 {
8570                         surface = texturesurfacelist[i];
8571                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8572                         surfacenumvertices = surface->num_vertices;
8573                         if (surface->lightmapinfo->samples)
8574                         {
8575                                 for (j = 0;j < surfacenumvertices;j++)
8576                                 {
8577                                         lm = surface->lightmapinfo->samples + offsets[j];
8578                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8579                                         VectorScale(lm, scale, c);
8580                                         if (surface->lightmapinfo->styles[1] != 255)
8581                                         {
8582                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8583                                                 lm += size3;
8584                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8585                                                 VectorMA(c, scale, lm, c);
8586                                                 if (surface->lightmapinfo->styles[2] != 255)
8587                                                 {
8588                                                         lm += size3;
8589                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8590                                                         VectorMA(c, scale, lm, c);
8591                                                         if (surface->lightmapinfo->styles[3] != 255)
8592                                                         {
8593                                                                 lm += size3;
8594                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8595                                                                 VectorMA(c, scale, lm, c);
8596                                                         }
8597                                                 }
8598                                         }
8599                                         c[0] >>= 7;
8600                                         c[1] >>= 7;
8601                                         c[2] >>= 7;
8602                                         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);
8603                                         numvertices++;
8604                                 }
8605                         }
8606                         else
8607                         {
8608                                 for (j = 0;j < surfacenumvertices;j++)
8609                                 {
8610                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8611                                         numvertices++;
8612                                 }
8613                         }
8614                 }
8615         }
8616
8617         // if vertices are deformed (sprite flares and things in maps, possibly
8618         // water waves, bulges and other deformations), modify the copied vertices
8619         // in place
8620         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8621         {
8622                 switch (deform->deform)
8623                 {
8624                 default:
8625                 case Q3DEFORM_PROJECTIONSHADOW:
8626                 case Q3DEFORM_TEXT0:
8627                 case Q3DEFORM_TEXT1:
8628                 case Q3DEFORM_TEXT2:
8629                 case Q3DEFORM_TEXT3:
8630                 case Q3DEFORM_TEXT4:
8631                 case Q3DEFORM_TEXT5:
8632                 case Q3DEFORM_TEXT6:
8633                 case Q3DEFORM_TEXT7:
8634                 case Q3DEFORM_NONE:
8635                         break;
8636                 case Q3DEFORM_AUTOSPRITE:
8637                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8638                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8639                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8640                         VectorNormalize(newforward);
8641                         VectorNormalize(newright);
8642                         VectorNormalize(newup);
8643 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8644 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8645 //                      rsurface.batchvertex3f_bufferoffset = 0;
8646 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8647 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8648 //                      rsurface.batchsvector3f_bufferoffset = 0;
8649 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8650 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8651 //                      rsurface.batchtvector3f_bufferoffset = 0;
8652 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8653 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8654 //                      rsurface.batchnormal3f_bufferoffset = 0;
8655                         // a single autosprite surface can contain multiple sprites...
8656                         for (j = 0;j < batchnumvertices - 3;j += 4)
8657                         {
8658                                 VectorClear(center);
8659                                 for (i = 0;i < 4;i++)
8660                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8661                                 VectorScale(center, 0.25f, center);
8662                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8663                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8664                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8665                                 for (i = 0;i < 4;i++)
8666                                 {
8667                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8668                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8669                                 }
8670                         }
8671                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8672                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8673                         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);
8674                         break;
8675                 case Q3DEFORM_AUTOSPRITE2:
8676                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8677                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8678                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8679                         VectorNormalize(newforward);
8680                         VectorNormalize(newright);
8681                         VectorNormalize(newup);
8682 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8683 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8684 //                      rsurface.batchvertex3f_bufferoffset = 0;
8685                         {
8686                                 const float *v1, *v2;
8687                                 vec3_t start, end;
8688                                 float f, l;
8689                                 struct
8690                                 {
8691                                         float length2;
8692                                         const float *v1;
8693                                         const float *v2;
8694                                 }
8695                                 shortest[2];
8696                                 memset(shortest, 0, sizeof(shortest));
8697                                 // a single autosprite surface can contain multiple sprites...
8698                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8699                                 {
8700                                         VectorClear(center);
8701                                         for (i = 0;i < 4;i++)
8702                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8703                                         VectorScale(center, 0.25f, center);
8704                                         // find the two shortest edges, then use them to define the
8705                                         // axis vectors for rotating around the central axis
8706                                         for (i = 0;i < 6;i++)
8707                                         {
8708                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8709                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8710                                                 l = VectorDistance2(v1, v2);
8711                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8712                                                 if (v1[2] != v2[2])
8713                                                         l += (1.0f / 1024.0f);
8714                                                 if (shortest[0].length2 > l || i == 0)
8715                                                 {
8716                                                         shortest[1] = shortest[0];
8717                                                         shortest[0].length2 = l;
8718                                                         shortest[0].v1 = v1;
8719                                                         shortest[0].v2 = v2;
8720                                                 }
8721                                                 else if (shortest[1].length2 > l || i == 1)
8722                                                 {
8723                                                         shortest[1].length2 = l;
8724                                                         shortest[1].v1 = v1;
8725                                                         shortest[1].v2 = v2;
8726                                                 }
8727                                         }
8728                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8729                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8730                                         // this calculates the right vector from the shortest edge
8731                                         // and the up vector from the edge midpoints
8732                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8733                                         VectorNormalize(right);
8734                                         VectorSubtract(end, start, up);
8735                                         VectorNormalize(up);
8736                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8737                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8738                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8739                                         VectorNegate(forward, forward);
8740                                         VectorReflect(forward, 0, up, forward);
8741                                         VectorNormalize(forward);
8742                                         CrossProduct(up, forward, newright);
8743                                         VectorNormalize(newright);
8744                                         // rotate the quad around the up axis vector, this is made
8745                                         // especially easy by the fact we know the quad is flat,
8746                                         // so we only have to subtract the center position and
8747                                         // measure distance along the right vector, and then
8748                                         // multiply that by the newright vector and add back the
8749                                         // center position
8750                                         // we also need to subtract the old position to undo the
8751                                         // displacement from the center, which we do with a
8752                                         // DotProduct, the subtraction/addition of center is also
8753                                         // optimized into DotProducts here
8754                                         l = DotProduct(right, center);
8755                                         for (i = 0;i < 4;i++)
8756                                         {
8757                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8758                                                 f = DotProduct(right, v1) - l;
8759                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8760                                         }
8761                                 }
8762                         }
8763                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8764                         {
8765 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8766 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8767 //                              rsurface.batchnormal3f_bufferoffset = 0;
8768                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8769                         }
8770                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8771                         {
8772 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8773 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8774 //                              rsurface.batchsvector3f_bufferoffset = 0;
8775 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8776 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8777 //                              rsurface.batchtvector3f_bufferoffset = 0;
8778                                 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);
8779                         }
8780                         break;
8781                 case Q3DEFORM_NORMAL:
8782                         // deform the normals to make reflections wavey
8783                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8784                         rsurface.batchnormal3f_vertexbuffer = NULL;
8785                         rsurface.batchnormal3f_bufferoffset = 0;
8786                         for (j = 0;j < batchnumvertices;j++)
8787                         {
8788                                 float vertex[3];
8789                                 float *normal = rsurface.batchnormal3f + 3*j;
8790                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8791                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8792                                 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]);
8793                                 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]);
8794                                 VectorNormalize(normal);
8795                         }
8796                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8797                         {
8798 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8799 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8800 //                              rsurface.batchsvector3f_bufferoffset = 0;
8801 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8802 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8803 //                              rsurface.batchtvector3f_bufferoffset = 0;
8804                                 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);
8805                         }
8806                         break;
8807                 case Q3DEFORM_WAVE:
8808                         // deform vertex array to make wavey water and flags and such
8809                         waveparms[0] = deform->waveparms[0];
8810                         waveparms[1] = deform->waveparms[1];
8811                         waveparms[2] = deform->waveparms[2];
8812                         waveparms[3] = deform->waveparms[3];
8813                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8814                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8815                         // this is how a divisor of vertex influence on deformation
8816                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8817                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8818 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8819 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8820 //                      rsurface.batchvertex3f_bufferoffset = 0;
8821 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8822 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8823 //                      rsurface.batchnormal3f_bufferoffset = 0;
8824                         for (j = 0;j < batchnumvertices;j++)
8825                         {
8826                                 // if the wavefunc depends on time, evaluate it per-vertex
8827                                 if (waveparms[3])
8828                                 {
8829                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8830                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8831                                 }
8832                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8833                         }
8834                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8835                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8836                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8837                         {
8838 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8839 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8840 //                              rsurface.batchsvector3f_bufferoffset = 0;
8841 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8842 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8843 //                              rsurface.batchtvector3f_bufferoffset = 0;
8844                                 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);
8845                         }
8846                         break;
8847                 case Q3DEFORM_BULGE:
8848                         // deform vertex array to make the surface have moving bulges
8849 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8850 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8851 //                      rsurface.batchvertex3f_bufferoffset = 0;
8852 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8853 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8854 //                      rsurface.batchnormal3f_bufferoffset = 0;
8855                         for (j = 0;j < batchnumvertices;j++)
8856                         {
8857                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8858                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8859                         }
8860                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8861                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8862                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8863                         {
8864 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8865 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8866 //                              rsurface.batchsvector3f_bufferoffset = 0;
8867 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8868 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8869 //                              rsurface.batchtvector3f_bufferoffset = 0;
8870                                 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);
8871                         }
8872                         break;
8873                 case Q3DEFORM_MOVE:
8874                         // deform vertex array
8875                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8876                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8877                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8878                         VectorScale(deform->parms, scale, waveparms);
8879 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8880 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8881 //                      rsurface.batchvertex3f_bufferoffset = 0;
8882                         for (j = 0;j < batchnumvertices;j++)
8883                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8884                         break;
8885                 }
8886         }
8887
8888         // generate texcoords based on the chosen texcoord source
8889         switch(rsurface.texture->tcgen.tcgen)
8890         {
8891         default:
8892         case Q3TCGEN_TEXTURE:
8893                 break;
8894         case Q3TCGEN_LIGHTMAP:
8895 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8896 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8897 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8898                 if (rsurface.batchtexcoordlightmap2f)
8899                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8900                 break;
8901         case Q3TCGEN_VECTOR:
8902 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8903 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8904 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8905                 for (j = 0;j < batchnumvertices;j++)
8906                 {
8907                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8908                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8909                 }
8910                 break;
8911         case Q3TCGEN_ENVIRONMENT:
8912                 // make environment reflections using a spheremap
8913                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8914                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8915                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8916                 for (j = 0;j < batchnumvertices;j++)
8917                 {
8918                         // identical to Q3A's method, but executed in worldspace so
8919                         // carried models can be shiny too
8920
8921                         float viewer[3], d, reflected[3], worldreflected[3];
8922
8923                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8924                         // VectorNormalize(viewer);
8925
8926                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8927
8928                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8929                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8930                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8931                         // note: this is proportinal to viewer, so we can normalize later
8932
8933                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8934                         VectorNormalize(worldreflected);
8935
8936                         // note: this sphere map only uses world x and z!
8937                         // so positive and negative y will LOOK THE SAME.
8938                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8939                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8940                 }
8941                 break;
8942         }
8943         // the only tcmod that needs software vertex processing is turbulent, so
8944         // check for it here and apply the changes if needed
8945         // and we only support that as the first one
8946         // (handling a mixture of turbulent and other tcmods would be problematic
8947         //  without punting it entirely to a software path)
8948         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8949         {
8950                 amplitude = rsurface.texture->tcmods[0].parms[1];
8951                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8952 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8953 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8954 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8955                 for (j = 0;j < batchnumvertices;j++)
8956                 {
8957                         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);
8958                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8959                 }
8960         }
8961
8962         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8963         {
8964                 // convert the modified arrays to vertex structs
8965 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8966 //              rsurface.batchvertexmeshbuffer = NULL;
8967                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8968                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8969                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8970                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8971                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8972                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8973                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8974                 {
8975                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8976                         {
8977                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8978                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8979                         }
8980                 }
8981                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8982                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8983                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8984                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8985                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8986                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8987                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8988                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8989                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8990         }
8991 }
8992
8993 void RSurf_DrawBatch(void)
8994 {
8995         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8996         // through the pipeline, killing it earlier in the pipeline would have
8997         // per-surface overhead rather than per-batch overhead, so it's best to
8998         // reject it here, before it hits glDraw.
8999         if (rsurface.batchnumtriangles == 0)
9000                 return;
9001 #if 0
9002         // batch debugging code
9003         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9004         {
9005                 int i;
9006                 int j;
9007                 int c;
9008                 const int *e;
9009                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9010                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9011                 {
9012                         c = e[i];
9013                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9014                         {
9015                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9016                                 {
9017                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9018                                                 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);
9019                                         break;
9020                                 }
9021                         }
9022                 }
9023         }
9024 #endif
9025         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);
9026 }
9027
9028 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9029 {
9030         // pick the closest matching water plane
9031         int planeindex, vertexindex, bestplaneindex = -1;
9032         float d, bestd;
9033         vec3_t vert;
9034         const float *v;
9035         r_waterstate_waterplane_t *p;
9036         qboolean prepared = false;
9037         bestd = 0;
9038         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9039         {
9040                 if(p->camera_entity != rsurface.texture->camera_entity)
9041                         continue;
9042                 d = 0;
9043                 if(!prepared)
9044                 {
9045                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9046                         prepared = true;
9047                         if(rsurface.batchnumvertices == 0)
9048                                 break;
9049                 }
9050                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9051                 {
9052                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9053                         d += fabs(PlaneDiff(vert, &p->plane));
9054                 }
9055                 if (bestd > d || bestplaneindex < 0)
9056                 {
9057                         bestd = d;
9058                         bestplaneindex = planeindex;
9059                 }
9060         }
9061         return bestplaneindex;
9062         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9063         // this situation though, as it might be better to render single larger
9064         // batches with useless stuff (backface culled for example) than to
9065         // render multiple smaller batches
9066 }
9067
9068 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9069 {
9070         int i;
9071         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9072         rsurface.passcolor4f_vertexbuffer = 0;
9073         rsurface.passcolor4f_bufferoffset = 0;
9074         for (i = 0;i < rsurface.batchnumvertices;i++)
9075                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9076 }
9077
9078 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9079 {
9080         int i;
9081         float f;
9082         const float *v;
9083         const float *c;
9084         float *c2;
9085         if (rsurface.passcolor4f)
9086         {
9087                 // generate color arrays
9088                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9089                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9090                 rsurface.passcolor4f_vertexbuffer = 0;
9091                 rsurface.passcolor4f_bufferoffset = 0;
9092                 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)
9093                 {
9094                         f = RSurf_FogVertex(v);
9095                         c2[0] = c[0] * f;
9096                         c2[1] = c[1] * f;
9097                         c2[2] = c[2] * f;
9098                         c2[3] = c[3];
9099                 }
9100         }
9101         else
9102         {
9103                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9104                 rsurface.passcolor4f_vertexbuffer = 0;
9105                 rsurface.passcolor4f_bufferoffset = 0;
9106                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9107                 {
9108                         f = RSurf_FogVertex(v);
9109                         c2[0] = f;
9110                         c2[1] = f;
9111                         c2[2] = f;
9112                         c2[3] = 1;
9113                 }
9114         }
9115 }
9116
9117 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9118 {
9119         int i;
9120         float f;
9121         const float *v;
9122         const float *c;
9123         float *c2;
9124         if (!rsurface.passcolor4f)
9125                 return;
9126         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9127         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9128         rsurface.passcolor4f_vertexbuffer = 0;
9129         rsurface.passcolor4f_bufferoffset = 0;
9130         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9131         {
9132                 f = RSurf_FogVertex(v);
9133                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9134                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9135                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9136                 c2[3] = c[3];
9137         }
9138 }
9139
9140 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9141 {
9142         int i;
9143         const float *c;
9144         float *c2;
9145         if (!rsurface.passcolor4f)
9146                 return;
9147         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9148         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9149         rsurface.passcolor4f_vertexbuffer = 0;
9150         rsurface.passcolor4f_bufferoffset = 0;
9151         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9152         {
9153                 c2[0] = c[0] * r;
9154                 c2[1] = c[1] * g;
9155                 c2[2] = c[2] * b;
9156                 c2[3] = c[3] * a;
9157         }
9158 }
9159
9160 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9161 {
9162         int i;
9163         const float *c;
9164         float *c2;
9165         if (!rsurface.passcolor4f)
9166                 return;
9167         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9168         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9169         rsurface.passcolor4f_vertexbuffer = 0;
9170         rsurface.passcolor4f_bufferoffset = 0;
9171         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9172         {
9173                 c2[0] = c[0] + r_refdef.scene.ambient;
9174                 c2[1] = c[1] + r_refdef.scene.ambient;
9175                 c2[2] = c[2] + r_refdef.scene.ambient;
9176                 c2[3] = c[3];
9177         }
9178 }
9179
9180 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9181 {
9182         // TODO: optimize
9183         rsurface.passcolor4f = NULL;
9184         rsurface.passcolor4f_vertexbuffer = 0;
9185         rsurface.passcolor4f_bufferoffset = 0;
9186         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9187         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9188         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9189         GL_Color(r, g, b, a);
9190         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9191         RSurf_DrawBatch();
9192 }
9193
9194 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9195 {
9196         // TODO: optimize applyfog && applycolor case
9197         // just apply fog if necessary, and tint the fog color array if necessary
9198         rsurface.passcolor4f = NULL;
9199         rsurface.passcolor4f_vertexbuffer = 0;
9200         rsurface.passcolor4f_bufferoffset = 0;
9201         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9202         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9203         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9204         GL_Color(r, g, b, a);
9205         RSurf_DrawBatch();
9206 }
9207
9208 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9209 {
9210         // TODO: optimize
9211         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9212         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9213         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9214         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9215         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9216         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9217         GL_Color(r, g, b, a);
9218         RSurf_DrawBatch();
9219 }
9220
9221 static void RSurf_DrawBatch_GL11_ClampColor(void)
9222 {
9223         int i;
9224         const float *c1;
9225         float *c2;
9226         if (!rsurface.passcolor4f)
9227                 return;
9228         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9229         {
9230                 c2[0] = bound(0.0f, c1[0], 1.0f);
9231                 c2[1] = bound(0.0f, c1[1], 1.0f);
9232                 c2[2] = bound(0.0f, c1[2], 1.0f);
9233                 c2[3] = bound(0.0f, c1[3], 1.0f);
9234         }
9235 }
9236
9237 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9238 {
9239         int i;
9240         float f;
9241         const float *v;
9242         const float *n;
9243         float *c;
9244         //vec3_t eyedir;
9245
9246         // fake shading
9247         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9248         rsurface.passcolor4f_vertexbuffer = 0;
9249         rsurface.passcolor4f_bufferoffset = 0;
9250         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)
9251         {
9252                 f = -DotProduct(r_refdef.view.forward, n);
9253                 f = max(0, f);
9254                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9255                 f *= r_refdef.lightmapintensity;
9256                 Vector4Set(c, f, f, f, 1);
9257         }
9258 }
9259
9260 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9261 {
9262         RSurf_DrawBatch_GL11_ApplyFakeLight();
9263         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9264         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9265         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9266         GL_Color(r, g, b, a);
9267         RSurf_DrawBatch();
9268 }
9269
9270 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9271 {
9272         int i;
9273         float f;
9274         float alpha;
9275         const float *v;
9276         const float *n;
9277         float *c;
9278         vec3_t ambientcolor;
9279         vec3_t diffusecolor;
9280         vec3_t lightdir;
9281         // TODO: optimize
9282         // model lighting
9283         VectorCopy(rsurface.modellight_lightdir, lightdir);
9284         f = 0.5f * r_refdef.lightmapintensity;
9285         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9286         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9287         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9288         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9289         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9290         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9291         alpha = *a;
9292         if (VectorLength2(diffusecolor) > 0)
9293         {
9294                 // q3-style directional shading
9295                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9296                 rsurface.passcolor4f_vertexbuffer = 0;
9297                 rsurface.passcolor4f_bufferoffset = 0;
9298                 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)
9299                 {
9300                         if ((f = DotProduct(n, lightdir)) > 0)
9301                                 VectorMA(ambientcolor, f, diffusecolor, c);
9302                         else
9303                                 VectorCopy(ambientcolor, c);
9304                         c[3] = alpha;
9305                 }
9306                 *r = 1;
9307                 *g = 1;
9308                 *b = 1;
9309                 *a = 1;
9310                 *applycolor = false;
9311         }
9312         else
9313         {
9314                 *r = ambientcolor[0];
9315                 *g = ambientcolor[1];
9316                 *b = ambientcolor[2];
9317                 rsurface.passcolor4f = NULL;
9318                 rsurface.passcolor4f_vertexbuffer = 0;
9319                 rsurface.passcolor4f_bufferoffset = 0;
9320         }
9321 }
9322
9323 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9324 {
9325         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9326         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9327         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9328         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9329         GL_Color(r, g, b, a);
9330         RSurf_DrawBatch();
9331 }
9332
9333 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9334 {
9335         int i;
9336         float f;
9337         const float *v;
9338         float *c;
9339
9340         // fake shading
9341         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9342         rsurface.passcolor4f_vertexbuffer = 0;
9343         rsurface.passcolor4f_bufferoffset = 0;
9344
9345         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9346         {
9347                 f = 1 - RSurf_FogVertex(v);
9348                 c[0] = r;
9349                 c[1] = g;
9350                 c[2] = b;
9351                 c[3] = f * a;
9352         }
9353 }
9354
9355 void RSurf_SetupDepthAndCulling(void)
9356 {
9357         // submodels are biased to avoid z-fighting with world surfaces that they
9358         // may be exactly overlapping (avoids z-fighting artifacts on certain
9359         // doors and things in Quake maps)
9360         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9361         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9362         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9363         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9364 }
9365
9366 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9367 {
9368         // transparent sky would be ridiculous
9369         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9370                 return;
9371         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9372         skyrenderlater = true;
9373         RSurf_SetupDepthAndCulling();
9374         GL_DepthMask(true);
9375         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9376         // skymasking on them, and Quake3 never did sky masking (unlike
9377         // software Quake and software Quake2), so disable the sky masking
9378         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9379         // and skymasking also looks very bad when noclipping outside the
9380         // level, so don't use it then either.
9381         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9382         {
9383                 R_Mesh_ResetTextureState();
9384                 if (skyrendermasked)
9385                 {
9386                         R_SetupShader_DepthOrShadow();
9387                         // depth-only (masking)
9388                         GL_ColorMask(0,0,0,0);
9389                         // just to make sure that braindead drivers don't draw
9390                         // anything despite that colormask...
9391                         GL_BlendFunc(GL_ZERO, GL_ONE);
9392                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9393                         if (rsurface.batchvertex3fbuffer)
9394                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9395                         else
9396                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9397                 }
9398                 else
9399                 {
9400                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9401                         // fog sky
9402                         GL_BlendFunc(GL_ONE, GL_ZERO);
9403                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9404                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9405                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9406                 }
9407                 RSurf_DrawBatch();
9408                 if (skyrendermasked)
9409                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9410         }
9411         R_Mesh_ResetTextureState();
9412         GL_Color(1, 1, 1, 1);
9413 }
9414
9415 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9416 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9417 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9418 {
9419         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9420                 return;
9421         if (prepass)
9422         {
9423                 // render screenspace normalmap to texture
9424                 GL_DepthMask(true);
9425                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9426                 RSurf_DrawBatch();
9427                 return;
9428         }
9429
9430         // bind lightmap texture
9431
9432         // water/refraction/reflection/camera surfaces have to be handled specially
9433         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9434         {
9435                 int start, end, startplaneindex;
9436                 for (start = 0;start < texturenumsurfaces;start = end)
9437                 {
9438                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9439                         if(startplaneindex < 0)
9440                         {
9441                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9442                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9443                                 end = start + 1;
9444                                 continue;
9445                         }
9446                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9447                                 ;
9448                         // now that we have a batch using the same planeindex, render it
9449                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9450                         {
9451                                 // render water or distortion background
9452                                 GL_DepthMask(true);
9453                                 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));
9454                                 RSurf_DrawBatch();
9455                                 // blend surface on top
9456                                 GL_DepthMask(false);
9457                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9458                                 RSurf_DrawBatch();
9459                         }
9460                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9461                         {
9462                                 // render surface with reflection texture as input
9463                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9464                                 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));
9465                                 RSurf_DrawBatch();
9466                         }
9467                 }
9468                 return;
9469         }
9470
9471         // render surface batch normally
9472         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9473         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9474         RSurf_DrawBatch();
9475 }
9476
9477 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9478 {
9479         // OpenGL 1.3 path - anything not completely ancient
9480         qboolean applycolor;
9481         qboolean applyfog;
9482         int layerindex;
9483         const texturelayer_t *layer;
9484         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);
9485         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9486
9487         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9488         {
9489                 vec4_t layercolor;
9490                 int layertexrgbscale;
9491                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9492                 {
9493                         if (layerindex == 0)
9494                                 GL_AlphaTest(true);
9495                         else
9496                         {
9497                                 GL_AlphaTest(false);
9498                                 GL_DepthFunc(GL_EQUAL);
9499                         }
9500                 }
9501                 GL_DepthMask(layer->depthmask && writedepth);
9502                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9503                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9504                 {
9505                         layertexrgbscale = 4;
9506                         VectorScale(layer->color, 0.25f, layercolor);
9507                 }
9508                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9509                 {
9510                         layertexrgbscale = 2;
9511                         VectorScale(layer->color, 0.5f, layercolor);
9512                 }
9513                 else
9514                 {
9515                         layertexrgbscale = 1;
9516                         VectorScale(layer->color, 1.0f, layercolor);
9517                 }
9518                 layercolor[3] = layer->color[3];
9519                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9520                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9521                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9522                 switch (layer->type)
9523                 {
9524                 case TEXTURELAYERTYPE_LITTEXTURE:
9525                         // single-pass lightmapped texture with 2x rgbscale
9526                         R_Mesh_TexBind(0, r_texture_white);
9527                         R_Mesh_TexMatrix(0, NULL);
9528                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9529                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9530                         R_Mesh_TexBind(1, layer->texture);
9531                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9532                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9533                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9534                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9535                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9536                         else if (FAKELIGHT_ENABLED)
9537                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9538                         else if (rsurface.uselightmaptexture)
9539                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9540                         else
9541                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9542                         break;
9543                 case TEXTURELAYERTYPE_TEXTURE:
9544                         // singletexture unlit texture with transparency support
9545                         R_Mesh_TexBind(0, layer->texture);
9546                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9547                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9548                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9549                         R_Mesh_TexBind(1, 0);
9550                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9551                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9552                         break;
9553                 case TEXTURELAYERTYPE_FOG:
9554                         // singletexture fogging
9555                         if (layer->texture)
9556                         {
9557                                 R_Mesh_TexBind(0, layer->texture);
9558                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9559                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9560                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9561                         }
9562                         else
9563                         {
9564                                 R_Mesh_TexBind(0, 0);
9565                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9566                         }
9567                         R_Mesh_TexBind(1, 0);
9568                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9569                         // generate a color array for the fog pass
9570                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9571                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9572                         RSurf_DrawBatch();
9573                         break;
9574                 default:
9575                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9576                 }
9577         }
9578         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9579         {
9580                 GL_DepthFunc(GL_LEQUAL);
9581                 GL_AlphaTest(false);
9582         }
9583 }
9584
9585 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9586 {
9587         // OpenGL 1.1 - crusty old voodoo path
9588         qboolean applyfog;
9589         int layerindex;
9590         const texturelayer_t *layer;
9591         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);
9592         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9593
9594         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9595         {
9596                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9597                 {
9598                         if (layerindex == 0)
9599                                 GL_AlphaTest(true);
9600                         else
9601                         {
9602                                 GL_AlphaTest(false);
9603                                 GL_DepthFunc(GL_EQUAL);
9604                         }
9605                 }
9606                 GL_DepthMask(layer->depthmask && writedepth);
9607                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9608                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9609                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9610                 switch (layer->type)
9611                 {
9612                 case TEXTURELAYERTYPE_LITTEXTURE:
9613                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9614                         {
9615                                 // two-pass lit texture with 2x rgbscale
9616                                 // first the lightmap pass
9617                                 R_Mesh_TexBind(0, r_texture_white);
9618                                 R_Mesh_TexMatrix(0, NULL);
9619                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9620                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9621                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9622                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9623                                 else if (FAKELIGHT_ENABLED)
9624                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9625                                 else if (rsurface.uselightmaptexture)
9626                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9627                                 else
9628                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9629                                 // then apply the texture to it
9630                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9631                                 R_Mesh_TexBind(0, layer->texture);
9632                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9633                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9634                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9635                                 RSurf_DrawBatch_GL11_Unlit(layer->color[0] * 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);
9636                         }
9637                         else
9638                         {
9639                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9640                                 R_Mesh_TexBind(0, layer->texture);
9641                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9642                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9643                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9644                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9645                                         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);
9646                                 else
9647                                         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);
9648                         }
9649                         break;
9650                 case TEXTURELAYERTYPE_TEXTURE:
9651                         // singletexture unlit texture with transparency support
9652                         R_Mesh_TexBind(0, layer->texture);
9653                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9654                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9655                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9656                         RSurf_DrawBatch_GL11_Unlit(layer->color[0], 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);
9657                         break;
9658                 case TEXTURELAYERTYPE_FOG:
9659                         // singletexture fogging
9660                         if (layer->texture)
9661                         {
9662                                 R_Mesh_TexBind(0, layer->texture);
9663                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9664                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9665                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9666                         }
9667                         else
9668                         {
9669                                 R_Mesh_TexBind(0, 0);
9670                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9671                         }
9672                         // generate a color array for the fog pass
9673                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9674                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9675                         RSurf_DrawBatch();
9676                         break;
9677                 default:
9678                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9679                 }
9680         }
9681         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9682         {
9683                 GL_DepthFunc(GL_LEQUAL);
9684                 GL_AlphaTest(false);
9685         }
9686 }
9687
9688 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9689 {
9690         int vi;
9691         int j;
9692         r_vertexgeneric_t *batchvertex;
9693         float c[4];
9694
9695 //      R_Mesh_ResetTextureState();
9696         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9697
9698         if(rsurface.texture && rsurface.texture->currentskinframe)
9699         {
9700                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9701                 c[3] *= rsurface.texture->currentalpha;
9702         }
9703         else
9704         {
9705                 c[0] = 1;
9706                 c[1] = 0;
9707                 c[2] = 1;
9708                 c[3] = 1;
9709         }
9710
9711         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9712         {
9713                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9714                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9715                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9716         }
9717
9718         // brighten it up (as texture value 127 means "unlit")
9719         c[0] *= 2 * r_refdef.view.colorscale;
9720         c[1] *= 2 * r_refdef.view.colorscale;
9721         c[2] *= 2 * r_refdef.view.colorscale;
9722
9723         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9724                 c[3] *= r_wateralpha.value;
9725
9726         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9727         {
9728                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9729                 GL_DepthMask(false);
9730         }
9731         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9732         {
9733                 GL_BlendFunc(GL_ONE, GL_ONE);
9734                 GL_DepthMask(false);
9735         }
9736         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9737         {
9738                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9739                 GL_DepthMask(false);
9740         }
9741         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9742         {
9743                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9744                 GL_DepthMask(false);
9745         }
9746         else
9747         {
9748                 GL_BlendFunc(GL_ONE, GL_ZERO);
9749                 GL_DepthMask(writedepth);
9750         }
9751
9752         if (r_showsurfaces.integer == 3)
9753         {
9754                 rsurface.passcolor4f = NULL;
9755
9756                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9757                 {
9758                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9759
9760                         rsurface.passcolor4f = NULL;
9761                         rsurface.passcolor4f_vertexbuffer = 0;
9762                         rsurface.passcolor4f_bufferoffset = 0;
9763                 }
9764                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9765                 {
9766                         qboolean applycolor = true;
9767                         float one = 1.0;
9768
9769                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9770
9771                         r_refdef.lightmapintensity = 1;
9772                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9773                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9774                 }
9775                 else if (FAKELIGHT_ENABLED)
9776                 {
9777                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9778
9779                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9780                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9781                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9782                 }
9783                 else
9784                 {
9785                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9786
9787                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9788                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9789                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9790                 }
9791
9792                 if(!rsurface.passcolor4f)
9793                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9794
9795                 RSurf_DrawBatch_GL11_ApplyAmbient();
9796                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9797                 if(r_refdef.fogenabled)
9798                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9799                 RSurf_DrawBatch_GL11_ClampColor();
9800
9801                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9802                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9803                 RSurf_DrawBatch();
9804         }
9805         else if (!r_refdef.view.showdebug)
9806         {
9807                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9808                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9809                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9810                 {
9811                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9812                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9813                 }
9814                 R_Mesh_PrepareVertices_Generic_Unlock();
9815                 RSurf_DrawBatch();
9816         }
9817         else if (r_showsurfaces.integer == 4)
9818         {
9819                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9820                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9821                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9822                 {
9823                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9824                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9825                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9826                 }
9827                 R_Mesh_PrepareVertices_Generic_Unlock();
9828                 RSurf_DrawBatch();
9829         }
9830         else if (r_showsurfaces.integer == 2)
9831         {
9832                 const int *e;
9833                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9834                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9835                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9836                 {
9837                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9838                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9839                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9840                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9841                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9842                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9843                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9844                 }
9845                 R_Mesh_PrepareVertices_Generic_Unlock();
9846                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9847         }
9848         else
9849         {
9850                 int texturesurfaceindex;
9851                 int k;
9852                 const msurface_t *surface;
9853                 float surfacecolor4f[4];
9854                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9855                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9856                 vi = 0;
9857                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9858                 {
9859                         surface = texturesurfacelist[texturesurfaceindex];
9860                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9861                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9862                         for (j = 0;j < surface->num_vertices;j++)
9863                         {
9864                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9865                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9866                                 vi++;
9867                         }
9868                 }
9869                 R_Mesh_PrepareVertices_Generic_Unlock();
9870                 RSurf_DrawBatch();
9871         }
9872 }
9873
9874 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9875 {
9876         CHECKGLERROR
9877         RSurf_SetupDepthAndCulling();
9878         if (r_showsurfaces.integer)
9879         {
9880                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9881                 return;
9882         }
9883         switch (vid.renderpath)
9884         {
9885         case RENDERPATH_GL20:
9886         case RENDERPATH_D3D9:
9887         case RENDERPATH_D3D10:
9888         case RENDERPATH_D3D11:
9889         case RENDERPATH_SOFT:
9890         case RENDERPATH_GLES2:
9891                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9892                 break;
9893         case RENDERPATH_GL13:
9894                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9895                 break;
9896         case RENDERPATH_GL11:
9897                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9898                 break;
9899         }
9900         CHECKGLERROR
9901 }
9902
9903 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9904 {
9905         CHECKGLERROR
9906         RSurf_SetupDepthAndCulling();
9907         if (r_showsurfaces.integer)
9908         {
9909                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9910                 return;
9911         }
9912         switch (vid.renderpath)
9913         {
9914         case RENDERPATH_GL20:
9915         case RENDERPATH_D3D9:
9916         case RENDERPATH_D3D10:
9917         case RENDERPATH_D3D11:
9918         case RENDERPATH_SOFT:
9919         case RENDERPATH_GLES2:
9920                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9921                 break;
9922         case RENDERPATH_GL13:
9923                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9924                 break;
9925         case RENDERPATH_GL11:
9926                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9927                 break;
9928         }
9929         CHECKGLERROR
9930 }
9931
9932 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9933 {
9934         int i, j;
9935         int texturenumsurfaces, endsurface;
9936         texture_t *texture;
9937         const msurface_t *surface;
9938 #define MAXBATCH_TRANSPARENTSURFACES 256
9939         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9940
9941         // if the model is static it doesn't matter what value we give for
9942         // wantnormals and wanttangents, so this logic uses only rules applicable
9943         // to a model, knowing that they are meaningless otherwise
9944         if (ent == r_refdef.scene.worldentity)
9945                 RSurf_ActiveWorldEntity();
9946         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9947                 RSurf_ActiveModelEntity(ent, false, false, false);
9948         else
9949         {
9950                 switch (vid.renderpath)
9951                 {
9952                 case RENDERPATH_GL20:
9953                 case RENDERPATH_D3D9:
9954                 case RENDERPATH_D3D10:
9955                 case RENDERPATH_D3D11:
9956                 case RENDERPATH_SOFT:
9957                 case RENDERPATH_GLES2:
9958                         RSurf_ActiveModelEntity(ent, true, true, false);
9959                         break;
9960                 case RENDERPATH_GL13:
9961                 case RENDERPATH_GL11:
9962                         RSurf_ActiveModelEntity(ent, true, false, false);
9963                         break;
9964                 }
9965         }
9966
9967         if (r_transparentdepthmasking.integer)
9968         {
9969                 qboolean setup = false;
9970                 for (i = 0;i < numsurfaces;i = j)
9971                 {
9972                         j = i + 1;
9973                         surface = rsurface.modelsurfaces + surfacelist[i];
9974                         texture = surface->texture;
9975                         rsurface.texture = R_GetCurrentTexture(texture);
9976                         rsurface.lightmaptexture = NULL;
9977                         rsurface.deluxemaptexture = NULL;
9978                         rsurface.uselightmaptexture = false;
9979                         // scan ahead until we find a different texture
9980                         endsurface = min(i + 1024, numsurfaces);
9981                         texturenumsurfaces = 0;
9982                         texturesurfacelist[texturenumsurfaces++] = surface;
9983                         for (;j < endsurface;j++)
9984                         {
9985                                 surface = rsurface.modelsurfaces + surfacelist[j];
9986                                 if (texture != surface->texture)
9987                                         break;
9988                                 texturesurfacelist[texturenumsurfaces++] = surface;
9989                         }
9990                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9991                                 continue;
9992                         // render the range of surfaces as depth
9993                         if (!setup)
9994                         {
9995                                 setup = true;
9996                                 GL_ColorMask(0,0,0,0);
9997                                 GL_Color(1,1,1,1);
9998                                 GL_DepthTest(true);
9999                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10000                                 GL_DepthMask(true);
10001 //                              R_Mesh_ResetTextureState();
10002                                 R_SetupShader_DepthOrShadow();
10003                         }
10004                         RSurf_SetupDepthAndCulling();
10005                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10006                         if (rsurface.batchvertex3fbuffer)
10007                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10008                         else
10009                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10010                         RSurf_DrawBatch();
10011                 }
10012                 if (setup)
10013                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10014         }
10015
10016         for (i = 0;i < numsurfaces;i = j)
10017         {
10018                 j = i + 1;
10019                 surface = rsurface.modelsurfaces + surfacelist[i];
10020                 texture = surface->texture;
10021                 rsurface.texture = R_GetCurrentTexture(texture);
10022                 // scan ahead until we find a different texture
10023                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10024                 texturenumsurfaces = 0;
10025                 texturesurfacelist[texturenumsurfaces++] = surface;
10026                 if(FAKELIGHT_ENABLED)
10027                 {
10028                         rsurface.lightmaptexture = NULL;
10029                         rsurface.deluxemaptexture = NULL;
10030                         rsurface.uselightmaptexture = false;
10031                         for (;j < endsurface;j++)
10032                         {
10033                                 surface = rsurface.modelsurfaces + surfacelist[j];
10034                                 if (texture != surface->texture)
10035                                         break;
10036                                 texturesurfacelist[texturenumsurfaces++] = surface;
10037                         }
10038                 }
10039                 else
10040                 {
10041                         rsurface.lightmaptexture = surface->lightmaptexture;
10042                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10043                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10044                         for (;j < endsurface;j++)
10045                         {
10046                                 surface = rsurface.modelsurfaces + surfacelist[j];
10047                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10048                                         break;
10049                                 texturesurfacelist[texturenumsurfaces++] = surface;
10050                         }
10051                 }
10052                 // render the range of surfaces
10053                 if (ent == r_refdef.scene.worldentity)
10054                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10055                 else
10056                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10057         }
10058         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10059 }
10060
10061 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10062 {
10063         // transparent surfaces get pushed off into the transparent queue
10064         int surfacelistindex;
10065         const msurface_t *surface;
10066         vec3_t tempcenter, center;
10067         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10068         {
10069                 surface = texturesurfacelist[surfacelistindex];
10070                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10071                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10072                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10073                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10074                 if (queueentity->transparent_offset) // transparent offset
10075                 {
10076                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10077                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10078                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10079                 }
10080                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10081         }
10082 }
10083
10084 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10085 {
10086         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10087                 return;
10088         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10089                 return;
10090         RSurf_SetupDepthAndCulling();
10091         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10092         if (rsurface.batchvertex3fbuffer)
10093                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10094         else
10095                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10096         RSurf_DrawBatch();
10097 }
10098
10099 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10100 {
10101         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10102         CHECKGLERROR
10103         if (depthonly)
10104                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10105         else if (prepass)
10106         {
10107                 if (!rsurface.texture->currentnumlayers)
10108                         return;
10109                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10110                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10111                 else
10112                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10113         }
10114         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10115                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10116         else if (!rsurface.texture->currentnumlayers)
10117                 return;
10118         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10119         {
10120                 // in the deferred case, transparent surfaces were queued during prepass
10121                 if (!r_shadow_usingdeferredprepass)
10122                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10123         }
10124         else
10125         {
10126                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10127                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10128         }
10129         CHECKGLERROR
10130 }
10131
10132 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10133 {
10134         int i, j;
10135         texture_t *texture;
10136         R_FrameData_SetMark();
10137         // break the surface list down into batches by texture and use of lightmapping
10138         for (i = 0;i < numsurfaces;i = j)
10139         {
10140                 j = i + 1;
10141                 // texture is the base texture pointer, rsurface.texture is the
10142                 // current frame/skin the texture is directing us to use (for example
10143                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10144                 // use skin 1 instead)
10145                 texture = surfacelist[i]->texture;
10146                 rsurface.texture = R_GetCurrentTexture(texture);
10147                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10148                 {
10149                         // if this texture is not the kind we want, skip ahead to the next one
10150                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10151                                 ;
10152                         continue;
10153                 }
10154                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10155                 {
10156                         rsurface.lightmaptexture = NULL;
10157                         rsurface.deluxemaptexture = NULL;
10158                         rsurface.uselightmaptexture = false;
10159                         // simply scan ahead until we find a different texture or lightmap state
10160                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10161                                 ;
10162                 }
10163                 else
10164                 {
10165                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10166                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10167                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10168                         // simply scan ahead until we find a different texture or lightmap state
10169                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10170                                 ;
10171                 }
10172                 // render the range of surfaces
10173                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10174         }
10175         R_FrameData_ReturnToMark();
10176 }
10177
10178 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10179 {
10180         CHECKGLERROR
10181         if (depthonly)
10182                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10183         else if (prepass)
10184         {
10185                 if (!rsurface.texture->currentnumlayers)
10186                         return;
10187                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10188                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10189                 else
10190                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10191         }
10192         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10193                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10194         else if (!rsurface.texture->currentnumlayers)
10195                 return;
10196         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10197         {
10198                 // in the deferred case, transparent surfaces were queued during prepass
10199                 if (!r_shadow_usingdeferredprepass)
10200                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10201         }
10202         else
10203         {
10204                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10205                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10206         }
10207         CHECKGLERROR
10208 }
10209
10210 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10211 {
10212         int i, j;
10213         texture_t *texture;
10214         R_FrameData_SetMark();
10215         // break the surface list down into batches by texture and use of lightmapping
10216         for (i = 0;i < numsurfaces;i = j)
10217         {
10218                 j = i + 1;
10219                 // texture is the base texture pointer, rsurface.texture is the
10220                 // current frame/skin the texture is directing us to use (for example
10221                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10222                 // use skin 1 instead)
10223                 texture = surfacelist[i]->texture;
10224                 rsurface.texture = R_GetCurrentTexture(texture);
10225                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10226                 {
10227                         // if this texture is not the kind we want, skip ahead to the next one
10228                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10229                                 ;
10230                         continue;
10231                 }
10232                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10233                 {
10234                         rsurface.lightmaptexture = NULL;
10235                         rsurface.deluxemaptexture = NULL;
10236                         rsurface.uselightmaptexture = false;
10237                         // simply scan ahead until we find a different texture or lightmap state
10238                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10239                                 ;
10240                 }
10241                 else
10242                 {
10243                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10244                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10245                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10246                         // simply scan ahead until we find a different texture or lightmap state
10247                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10248                                 ;
10249                 }
10250                 // render the range of surfaces
10251                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10252         }
10253         R_FrameData_ReturnToMark();
10254 }
10255
10256 float locboxvertex3f[6*4*3] =
10257 {
10258         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10259         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10260         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10261         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10262         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10263         1,0,0, 0,0,0, 0,1,0, 1,1,0
10264 };
10265
10266 unsigned short locboxelements[6*2*3] =
10267 {
10268          0, 1, 2, 0, 2, 3,
10269          4, 5, 6, 4, 6, 7,
10270          8, 9,10, 8,10,11,
10271         12,13,14, 12,14,15,
10272         16,17,18, 16,18,19,
10273         20,21,22, 20,22,23
10274 };
10275
10276 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10277 {
10278         int i, j;
10279         cl_locnode_t *loc = (cl_locnode_t *)ent;
10280         vec3_t mins, size;
10281         float vertex3f[6*4*3];
10282         CHECKGLERROR
10283         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10284         GL_DepthMask(false);
10285         GL_DepthRange(0, 1);
10286         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10287         GL_DepthTest(true);
10288         GL_CullFace(GL_NONE);
10289         R_EntityMatrix(&identitymatrix);
10290
10291 //      R_Mesh_ResetTextureState();
10292
10293         i = surfacelist[0];
10294         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10295                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10296                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10297                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10298
10299         if (VectorCompare(loc->mins, loc->maxs))
10300         {
10301                 VectorSet(size, 2, 2, 2);
10302                 VectorMA(loc->mins, -0.5f, size, mins);
10303         }
10304         else
10305         {
10306                 VectorCopy(loc->mins, mins);
10307                 VectorSubtract(loc->maxs, loc->mins, size);
10308         }
10309
10310         for (i = 0;i < 6*4*3;)
10311                 for (j = 0;j < 3;j++, i++)
10312                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10313
10314         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10315         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10316         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10317 }
10318
10319 void R_DrawLocs(void)
10320 {
10321         int index;
10322         cl_locnode_t *loc, *nearestloc;
10323         vec3_t center;
10324         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10325         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10326         {
10327                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10328                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10329         }
10330 }
10331
10332 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10333 {
10334         if (decalsystem->decals)
10335                 Mem_Free(decalsystem->decals);
10336         memset(decalsystem, 0, sizeof(*decalsystem));
10337 }
10338
10339 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)
10340 {
10341         tridecal_t *decal;
10342         tridecal_t *decals;
10343         int i;
10344
10345         // expand or initialize the system
10346         if (decalsystem->maxdecals <= decalsystem->numdecals)
10347         {
10348                 decalsystem_t old = *decalsystem;
10349                 qboolean useshortelements;
10350                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10351                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10352                 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)));
10353                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10354                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10355                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10356                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10357                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10358                 if (decalsystem->numdecals)
10359                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10360                 if (old.decals)
10361                         Mem_Free(old.decals);
10362                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10363                         decalsystem->element3i[i] = i;
10364                 if (useshortelements)
10365                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10366                                 decalsystem->element3s[i] = i;
10367         }
10368
10369         // grab a decal and search for another free slot for the next one
10370         decals = decalsystem->decals;
10371         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10372         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10373                 ;
10374         decalsystem->freedecal = i;
10375         if (decalsystem->numdecals <= i)
10376                 decalsystem->numdecals = i + 1;
10377
10378         // initialize the decal
10379         decal->lived = 0;
10380         decal->triangleindex = triangleindex;
10381         decal->surfaceindex = surfaceindex;
10382         decal->decalsequence = decalsequence;
10383         decal->color4f[0][0] = c0[0];
10384         decal->color4f[0][1] = c0[1];
10385         decal->color4f[0][2] = c0[2];
10386         decal->color4f[0][3] = 1;
10387         decal->color4f[1][0] = c1[0];
10388         decal->color4f[1][1] = c1[1];
10389         decal->color4f[1][2] = c1[2];
10390         decal->color4f[1][3] = 1;
10391         decal->color4f[2][0] = c2[0];
10392         decal->color4f[2][1] = c2[1];
10393         decal->color4f[2][2] = c2[2];
10394         decal->color4f[2][3] = 1;
10395         decal->vertex3f[0][0] = v0[0];
10396         decal->vertex3f[0][1] = v0[1];
10397         decal->vertex3f[0][2] = v0[2];
10398         decal->vertex3f[1][0] = v1[0];
10399         decal->vertex3f[1][1] = v1[1];
10400         decal->vertex3f[1][2] = v1[2];
10401         decal->vertex3f[2][0] = v2[0];
10402         decal->vertex3f[2][1] = v2[1];
10403         decal->vertex3f[2][2] = v2[2];
10404         decal->texcoord2f[0][0] = t0[0];
10405         decal->texcoord2f[0][1] = t0[1];
10406         decal->texcoord2f[1][0] = t1[0];
10407         decal->texcoord2f[1][1] = t1[1];
10408         decal->texcoord2f[2][0] = t2[0];
10409         decal->texcoord2f[2][1] = t2[1];
10410         TriangleNormal(v0, v1, v2, decal->plane);
10411         VectorNormalize(decal->plane);
10412         decal->plane[3] = DotProduct(v0, decal->plane);
10413 }
10414
10415 extern cvar_t cl_decals_bias;
10416 extern cvar_t cl_decals_models;
10417 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10418 // baseparms, parms, temps
10419 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)
10420 {
10421         int cornerindex;
10422         int index;
10423         float v[9][3];
10424         const float *vertex3f;
10425         const float *normal3f;
10426         int numpoints;
10427         float points[2][9][3];
10428         float temp[3];
10429         float tc[9][2];
10430         float f;
10431         float c[9][4];
10432         const int *e;
10433
10434         e = rsurface.modelelement3i + 3*triangleindex;
10435
10436         vertex3f = rsurface.modelvertex3f;
10437         normal3f = rsurface.modelnormal3f;
10438
10439         if (normal3f)
10440         {
10441                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10442                 {
10443                         index = 3*e[cornerindex];
10444                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10445                 }
10446         }
10447         else
10448         {
10449                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10450                 {
10451                         index = 3*e[cornerindex];
10452                         VectorCopy(vertex3f + index, v[cornerindex]);
10453                 }
10454         }
10455
10456         // cull backfaces
10457         //TriangleNormal(v[0], v[1], v[2], normal);
10458         //if (DotProduct(normal, localnormal) < 0.0f)
10459         //      continue;
10460         // clip by each of the box planes formed from the projection matrix
10461         // if anything survives, we emit the decal
10462         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]);
10463         if (numpoints < 3)
10464                 return;
10465         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]);
10466         if (numpoints < 3)
10467                 return;
10468         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]);
10469         if (numpoints < 3)
10470                 return;
10471         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]);
10472         if (numpoints < 3)
10473                 return;
10474         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]);
10475         if (numpoints < 3)
10476                 return;
10477         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]);
10478         if (numpoints < 3)
10479                 return;
10480         // some part of the triangle survived, so we have to accept it...
10481         if (dynamic)
10482         {
10483                 // dynamic always uses the original triangle
10484                 numpoints = 3;
10485                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10486                 {
10487                         index = 3*e[cornerindex];
10488                         VectorCopy(vertex3f + index, v[cornerindex]);
10489                 }
10490         }
10491         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10492         {
10493                 // convert vertex positions to texcoords
10494                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10495                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10496                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10497                 // calculate distance fade from the projection origin
10498                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10499                 f = bound(0.0f, f, 1.0f);
10500                 c[cornerindex][0] = r * f;
10501                 c[cornerindex][1] = g * f;
10502                 c[cornerindex][2] = b * f;
10503                 c[cornerindex][3] = 1.0f;
10504                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10505         }
10506         if (dynamic)
10507                 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);
10508         else
10509                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10510                         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);
10511 }
10512 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)
10513 {
10514         matrix4x4_t projection;
10515         decalsystem_t *decalsystem;
10516         qboolean dynamic;
10517         dp_model_t *model;
10518         const msurface_t *surface;
10519         const msurface_t *surfaces;
10520         const int *surfacelist;
10521         const texture_t *texture;
10522         int numtriangles;
10523         int numsurfacelist;
10524         int surfacelistindex;
10525         int surfaceindex;
10526         int triangleindex;
10527         float localorigin[3];
10528         float localnormal[3];
10529         float localmins[3];
10530         float localmaxs[3];
10531         float localsize;
10532         //float normal[3];
10533         float planes[6][4];
10534         float angles[3];
10535         bih_t *bih;
10536         int bih_triangles_count;
10537         int bih_triangles[256];
10538         int bih_surfaces[256];
10539
10540         decalsystem = &ent->decalsystem;
10541         model = ent->model;
10542         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10543         {
10544                 R_DecalSystem_Reset(&ent->decalsystem);
10545                 return;
10546         }
10547
10548         if (!model->brush.data_leafs && !cl_decals_models.integer)
10549         {
10550                 if (decalsystem->model)
10551                         R_DecalSystem_Reset(decalsystem);
10552                 return;
10553         }
10554
10555         if (decalsystem->model != model)
10556                 R_DecalSystem_Reset(decalsystem);
10557         decalsystem->model = model;
10558
10559         RSurf_ActiveModelEntity(ent, true, false, false);
10560
10561         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10562         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10563         VectorNormalize(localnormal);
10564         localsize = worldsize*rsurface.inversematrixscale;
10565         localmins[0] = localorigin[0] - localsize;
10566         localmins[1] = localorigin[1] - localsize;
10567         localmins[2] = localorigin[2] - localsize;
10568         localmaxs[0] = localorigin[0] + localsize;
10569         localmaxs[1] = localorigin[1] + localsize;
10570         localmaxs[2] = localorigin[2] + localsize;
10571
10572         //VectorCopy(localnormal, planes[4]);
10573         //VectorVectors(planes[4], planes[2], planes[0]);
10574         AnglesFromVectors(angles, localnormal, NULL, false);
10575         AngleVectors(angles, planes[0], planes[2], planes[4]);
10576         VectorNegate(planes[0], planes[1]);
10577         VectorNegate(planes[2], planes[3]);
10578         VectorNegate(planes[4], planes[5]);
10579         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10580         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10581         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10582         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10583         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10584         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10585
10586 #if 1
10587 // works
10588 {
10589         matrix4x4_t forwardprojection;
10590         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10591         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10592 }
10593 #else
10594 // broken
10595 {
10596         float projectionvector[4][3];
10597         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10598         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10599         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10600         projectionvector[0][0] = planes[0][0] * ilocalsize;
10601         projectionvector[0][1] = planes[1][0] * ilocalsize;
10602         projectionvector[0][2] = planes[2][0] * ilocalsize;
10603         projectionvector[1][0] = planes[0][1] * ilocalsize;
10604         projectionvector[1][1] = planes[1][1] * ilocalsize;
10605         projectionvector[1][2] = planes[2][1] * ilocalsize;
10606         projectionvector[2][0] = planes[0][2] * ilocalsize;
10607         projectionvector[2][1] = planes[1][2] * ilocalsize;
10608         projectionvector[2][2] = planes[2][2] * ilocalsize;
10609         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10610         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10611         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10612         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10613 }
10614 #endif
10615
10616         dynamic = model->surfmesh.isanimated;
10617         numsurfacelist = model->nummodelsurfaces;
10618         surfacelist = model->sortedmodelsurfaces;
10619         surfaces = model->data_surfaces;
10620
10621         bih = NULL;
10622         bih_triangles_count = -1;
10623         if(!dynamic)
10624         {
10625                 if(model->render_bih.numleafs)
10626                         bih = &model->render_bih;
10627                 else if(model->collision_bih.numleafs)
10628                         bih = &model->collision_bih;
10629         }
10630         if(bih)
10631                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10632         if(bih_triangles_count == 0)
10633                 return;
10634         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10635                 return;
10636         if(bih_triangles_count > 0)
10637         {
10638                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10639                 {
10640                         surfaceindex = bih_surfaces[triangleindex];
10641                         surface = surfaces + surfaceindex;
10642                         texture = surface->texture;
10643                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10644                                 continue;
10645                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10646                                 continue;
10647                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10648                 }
10649         }
10650         else
10651         {
10652                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10653                 {
10654                         surfaceindex = surfacelist[surfacelistindex];
10655                         surface = surfaces + surfaceindex;
10656                         // check cull box first because it rejects more than any other check
10657                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10658                                 continue;
10659                         // skip transparent surfaces
10660                         texture = surface->texture;
10661                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10662                                 continue;
10663                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10664                                 continue;
10665                         numtriangles = surface->num_triangles;
10666                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10667                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10668                 }
10669         }
10670 }
10671
10672 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10673 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)
10674 {
10675         int renderentityindex;
10676         float worldmins[3];
10677         float worldmaxs[3];
10678         entity_render_t *ent;
10679
10680         if (!cl_decals_newsystem.integer)
10681                 return;
10682
10683         worldmins[0] = worldorigin[0] - worldsize;
10684         worldmins[1] = worldorigin[1] - worldsize;
10685         worldmins[2] = worldorigin[2] - worldsize;
10686         worldmaxs[0] = worldorigin[0] + worldsize;
10687         worldmaxs[1] = worldorigin[1] + worldsize;
10688         worldmaxs[2] = worldorigin[2] + worldsize;
10689
10690         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10691
10692         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10693         {
10694                 ent = r_refdef.scene.entities[renderentityindex];
10695                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10696                         continue;
10697
10698                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10699         }
10700 }
10701
10702 typedef struct r_decalsystem_splatqueue_s
10703 {
10704         vec3_t worldorigin;
10705         vec3_t worldnormal;
10706         float color[4];
10707         float tcrange[4];
10708         float worldsize;
10709         int decalsequence;
10710 }
10711 r_decalsystem_splatqueue_t;
10712
10713 int r_decalsystem_numqueued = 0;
10714 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10715
10716 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)
10717 {
10718         r_decalsystem_splatqueue_t *queue;
10719
10720         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10721                 return;
10722
10723         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10724         VectorCopy(worldorigin, queue->worldorigin);
10725         VectorCopy(worldnormal, queue->worldnormal);
10726         Vector4Set(queue->color, r, g, b, a);
10727         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10728         queue->worldsize = worldsize;
10729         queue->decalsequence = cl.decalsequence++;
10730 }
10731
10732 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10733 {
10734         int i;
10735         r_decalsystem_splatqueue_t *queue;
10736
10737         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10738                 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);
10739         r_decalsystem_numqueued = 0;
10740 }
10741
10742 extern cvar_t cl_decals_max;
10743 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10744 {
10745         int i;
10746         decalsystem_t *decalsystem = &ent->decalsystem;
10747         int numdecals;
10748         int killsequence;
10749         tridecal_t *decal;
10750         float frametime;
10751         float lifetime;
10752
10753         if (!decalsystem->numdecals)
10754                 return;
10755
10756         if (r_showsurfaces.integer)
10757                 return;
10758
10759         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10760         {
10761                 R_DecalSystem_Reset(decalsystem);
10762                 return;
10763         }
10764
10765         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10766         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10767
10768         if (decalsystem->lastupdatetime)
10769                 frametime = (cl.time - decalsystem->lastupdatetime);
10770         else
10771                 frametime = 0;
10772         decalsystem->lastupdatetime = cl.time;
10773         decal = decalsystem->decals;
10774         numdecals = decalsystem->numdecals;
10775
10776         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10777         {
10778                 if (decal->color4f[0][3])
10779                 {
10780                         decal->lived += frametime;
10781                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10782                         {
10783                                 memset(decal, 0, sizeof(*decal));
10784                                 if (decalsystem->freedecal > i)
10785                                         decalsystem->freedecal = i;
10786                         }
10787                 }
10788         }
10789         decal = decalsystem->decals;
10790         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10791                 numdecals--;
10792
10793         // collapse the array by shuffling the tail decals into the gaps
10794         for (;;)
10795         {
10796                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10797                         decalsystem->freedecal++;
10798                 if (decalsystem->freedecal == numdecals)
10799                         break;
10800                 decal[decalsystem->freedecal] = decal[--numdecals];
10801         }
10802
10803         decalsystem->numdecals = numdecals;
10804
10805         if (numdecals <= 0)
10806         {
10807                 // if there are no decals left, reset decalsystem
10808                 R_DecalSystem_Reset(decalsystem);
10809         }
10810 }
10811
10812 extern skinframe_t *decalskinframe;
10813 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10814 {
10815         int i;
10816         decalsystem_t *decalsystem = &ent->decalsystem;
10817         int numdecals;
10818         tridecal_t *decal;
10819         float faderate;
10820         float alpha;
10821         float *v3f;
10822         float *c4f;
10823         float *t2f;
10824         const int *e;
10825         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10826         int numtris = 0;
10827
10828         numdecals = decalsystem->numdecals;
10829         if (!numdecals)
10830                 return;
10831
10832         if (r_showsurfaces.integer)
10833                 return;
10834
10835         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10836         {
10837                 R_DecalSystem_Reset(decalsystem);
10838                 return;
10839         }
10840
10841         // if the model is static it doesn't matter what value we give for
10842         // wantnormals and wanttangents, so this logic uses only rules applicable
10843         // to a model, knowing that they are meaningless otherwise
10844         if (ent == r_refdef.scene.worldentity)
10845                 RSurf_ActiveWorldEntity();
10846         else
10847                 RSurf_ActiveModelEntity(ent, false, false, false);
10848
10849         decalsystem->lastupdatetime = cl.time;
10850         decal = decalsystem->decals;
10851
10852         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10853
10854         // update vertex positions for animated models
10855         v3f = decalsystem->vertex3f;
10856         c4f = decalsystem->color4f;
10857         t2f = decalsystem->texcoord2f;
10858         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10859         {
10860                 if (!decal->color4f[0][3])
10861                         continue;
10862
10863                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10864                         continue;
10865
10866                 // skip backfaces
10867                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10868                         continue;
10869
10870                 // update color values for fading decals
10871                 if (decal->lived >= cl_decals_time.value)
10872                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10873                 else
10874                         alpha = 1.0f;
10875
10876                 c4f[ 0] = decal->color4f[0][0] * alpha;
10877                 c4f[ 1] = decal->color4f[0][1] * alpha;
10878                 c4f[ 2] = decal->color4f[0][2] * alpha;
10879                 c4f[ 3] = 1;
10880                 c4f[ 4] = decal->color4f[1][0] * alpha;
10881                 c4f[ 5] = decal->color4f[1][1] * alpha;
10882                 c4f[ 6] = decal->color4f[1][2] * alpha;
10883                 c4f[ 7] = 1;
10884                 c4f[ 8] = decal->color4f[2][0] * alpha;
10885                 c4f[ 9] = decal->color4f[2][1] * alpha;
10886                 c4f[10] = decal->color4f[2][2] * alpha;
10887                 c4f[11] = 1;
10888
10889                 t2f[0] = decal->texcoord2f[0][0];
10890                 t2f[1] = decal->texcoord2f[0][1];
10891                 t2f[2] = decal->texcoord2f[1][0];
10892                 t2f[3] = decal->texcoord2f[1][1];
10893                 t2f[4] = decal->texcoord2f[2][0];
10894                 t2f[5] = decal->texcoord2f[2][1];
10895
10896                 // update vertex positions for animated models
10897                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10898                 {
10899                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10900                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10901                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10902                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10903                 }
10904                 else
10905                 {
10906                         VectorCopy(decal->vertex3f[0], v3f);
10907                         VectorCopy(decal->vertex3f[1], v3f + 3);
10908                         VectorCopy(decal->vertex3f[2], v3f + 6);
10909                 }
10910
10911                 if (r_refdef.fogenabled)
10912                 {
10913                         alpha = RSurf_FogVertex(v3f);
10914                         VectorScale(c4f, alpha, c4f);
10915                         alpha = RSurf_FogVertex(v3f + 3);
10916                         VectorScale(c4f + 4, alpha, c4f + 4);
10917                         alpha = RSurf_FogVertex(v3f + 6);
10918                         VectorScale(c4f + 8, alpha, c4f + 8);
10919                 }
10920
10921                 v3f += 9;
10922                 c4f += 12;
10923                 t2f += 6;
10924                 numtris++;
10925         }
10926
10927         if (numtris > 0)
10928         {
10929                 r_refdef.stats.drawndecals += numtris;
10930
10931                 // now render the decals all at once
10932                 // (this assumes they all use one particle font texture!)
10933                 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);
10934 //              R_Mesh_ResetTextureState();
10935                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10936                 GL_DepthMask(false);
10937                 GL_DepthRange(0, 1);
10938                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10939                 GL_DepthTest(true);
10940                 GL_CullFace(GL_NONE);
10941                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10942                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10943                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10944         }
10945 }
10946
10947 static void R_DrawModelDecals(void)
10948 {
10949         int i, numdecals;
10950
10951         // fade faster when there are too many decals
10952         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10953         for (i = 0;i < r_refdef.scene.numentities;i++)
10954                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10955
10956         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10957         for (i = 0;i < r_refdef.scene.numentities;i++)
10958                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10959                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10960
10961         R_DecalSystem_ApplySplatEntitiesQueue();
10962
10963         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10964         for (i = 0;i < r_refdef.scene.numentities;i++)
10965                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10966
10967         r_refdef.stats.totaldecals += numdecals;
10968
10969         if (r_showsurfaces.integer)
10970                 return;
10971
10972         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10973
10974         for (i = 0;i < r_refdef.scene.numentities;i++)
10975         {
10976                 if (!r_refdef.viewcache.entityvisible[i])
10977                         continue;
10978                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10979                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10980         }
10981 }
10982
10983 extern cvar_t mod_collision_bih;
10984 void R_DrawDebugModel(void)
10985 {
10986         entity_render_t *ent = rsurface.entity;
10987         int i, j, k, l, flagsmask;
10988         const msurface_t *surface;
10989         dp_model_t *model = ent->model;
10990         vec3_t v;
10991
10992         if (r_showoverdraw.value > 0 && (sv.active || ent != r_refdef.scene.worldentity))
10993         {
10994                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
10995                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10996                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10997                 GL_DepthTest(false);
10998                 GL_DepthMask(false);
10999                 GL_DepthRange(0, 1);
11000                 GL_BlendFunc(GL_ONE, GL_ONE);
11001                 GL_CullFace(GL_NONE);
11002                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11003                 {
11004                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11005                                 continue;
11006                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11007                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11008                         {
11009                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11010                                 if (!rsurface.texture->currentlayers->depthmask)
11011                                         GL_Color(c, 0, 0, 1.0f);
11012                                 else if (ent == r_refdef.scene.worldentity)
11013                                         GL_Color(c, c, c, 1.0f);
11014                                 else
11015                                         GL_Color(0, c, 0, 1.0f);
11016                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11017                                 RSurf_DrawBatch();
11018                         }
11019                 }
11020                 rsurface.texture = NULL;
11021         }
11022
11023         switch(vid.renderpath)
11024         {
11025         case RENDERPATH_GL11:
11026         case RENDERPATH_GL13:
11027         case RENDERPATH_GL20:
11028                 break;
11029         case RENDERPATH_D3D9:
11030                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11031                 return;
11032         case RENDERPATH_D3D10:
11033                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11034                 return;
11035         case RENDERPATH_D3D11:
11036                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11037                 return;
11038         case RENDERPATH_SOFT:
11039                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11040                 return;
11041         case RENDERPATH_GLES2:
11042                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11043                 return;
11044         }
11045
11046         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11047
11048 //      R_Mesh_ResetTextureState();
11049         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11050         GL_DepthRange(0, 1);
11051         GL_DepthTest(!r_showdisabledepthtest.integer);
11052         GL_DepthMask(false);
11053         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11054
11055         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11056         {
11057                 int triangleindex;
11058                 int bihleafindex;
11059                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11060                 const q3mbrush_t *brush;
11061                 const bih_t *bih = &model->collision_bih;
11062                 const bih_leaf_t *bihleaf;
11063                 float vertex3f[3][3];
11064                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11065                 cullbox = false;
11066                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11067                 {
11068                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11069                                 continue;
11070                         switch (bihleaf->type)
11071                         {
11072                         case BIH_BRUSH:
11073                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11074                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11075                                 {
11076                                         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);
11077                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11078                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11079                                 }
11080                                 break;
11081                         case BIH_COLLISIONTRIANGLE:
11082                                 triangleindex = bihleaf->itemindex;
11083                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11084                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11085                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11086                                 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);
11087                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11088                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11089                                 break;
11090                         case BIH_RENDERTRIANGLE:
11091                                 triangleindex = bihleaf->itemindex;
11092                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11093                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11094                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11095                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11096                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11097                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11098                                 break;
11099                         }
11100                 }
11101         }
11102
11103         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11104
11105         if (r_showtris.integer || (r_shownormals.value != 0))
11106         {
11107                 if (r_showdisabledepthtest.integer)
11108                 {
11109                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11110                         GL_DepthMask(false);
11111                 }
11112                 else
11113                 {
11114                         GL_BlendFunc(GL_ONE, GL_ZERO);
11115                         GL_DepthMask(true);
11116                 }
11117                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11118                 {
11119                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11120                                 continue;
11121                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11122                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11123                         {
11124                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11125                                 if (r_showtris.value > 0)
11126                                 {
11127                                         if (!rsurface.texture->currentlayers->depthmask)
11128                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11129                                         else if (ent == r_refdef.scene.worldentity)
11130                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11131                                         else
11132                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11133                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11134                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11135                                         RSurf_DrawBatch();
11136                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11137                                         CHECKGLERROR
11138                                 }
11139                                 if (r_shownormals.value < 0)
11140                                 {
11141                                         qglBegin(GL_LINES);
11142                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11143                                         {
11144                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11145                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11146                                                 qglVertex3f(v[0], v[1], v[2]);
11147                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11148                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11149                                                 qglVertex3f(v[0], v[1], v[2]);
11150                                         }
11151                                         qglEnd();
11152                                         CHECKGLERROR
11153                                 }
11154                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11155                                 {
11156                                         qglBegin(GL_LINES);
11157                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11158                                         {
11159                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11160                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11161                                                 qglVertex3f(v[0], v[1], v[2]);
11162                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11163                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11164                                                 qglVertex3f(v[0], v[1], v[2]);
11165                                         }
11166                                         qglEnd();
11167                                         CHECKGLERROR
11168                                         qglBegin(GL_LINES);
11169                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11170                                         {
11171                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11172                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11173                                                 qglVertex3f(v[0], v[1], v[2]);
11174                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11175                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11176                                                 qglVertex3f(v[0], v[1], v[2]);
11177                                         }
11178                                         qglEnd();
11179                                         CHECKGLERROR
11180                                         qglBegin(GL_LINES);
11181                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11182                                         {
11183                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11184                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11185                                                 qglVertex3f(v[0], v[1], v[2]);
11186                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11187                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11188                                                 qglVertex3f(v[0], v[1], v[2]);
11189                                         }
11190                                         qglEnd();
11191                                         CHECKGLERROR
11192                                 }
11193                         }
11194                 }
11195                 rsurface.texture = NULL;
11196         }
11197 }
11198
11199 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11200 int r_maxsurfacelist = 0;
11201 const msurface_t **r_surfacelist = NULL;
11202 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11203 {
11204         int i, j, endj, flagsmask;
11205         dp_model_t *model = r_refdef.scene.worldmodel;
11206         msurface_t *surfaces;
11207         unsigned char *update;
11208         int numsurfacelist = 0;
11209         if (model == NULL)
11210                 return;
11211
11212         if (r_maxsurfacelist < model->num_surfaces)
11213         {
11214                 r_maxsurfacelist = model->num_surfaces;
11215                 if (r_surfacelist)
11216                         Mem_Free((msurface_t**)r_surfacelist);
11217                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11218         }
11219
11220         RSurf_ActiveWorldEntity();
11221
11222         surfaces = model->data_surfaces;
11223         update = model->brushq1.lightmapupdateflags;
11224
11225         // update light styles on this submodel
11226         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11227         {
11228                 model_brush_lightstyleinfo_t *style;
11229                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11230                 {
11231                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11232                         {
11233                                 int *list = style->surfacelist;
11234                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11235                                 for (j = 0;j < style->numsurfaces;j++)
11236                                         update[list[j]] = true;
11237                         }
11238                 }
11239         }
11240
11241         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11242
11243         if (debug)
11244         {
11245                 R_DrawDebugModel();
11246                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11247                 return;
11248         }
11249
11250         rsurface.lightmaptexture = NULL;
11251         rsurface.deluxemaptexture = NULL;
11252         rsurface.uselightmaptexture = false;
11253         rsurface.texture = NULL;
11254         rsurface.rtlight = NULL;
11255         numsurfacelist = 0;
11256         // add visible surfaces to draw list
11257         for (i = 0;i < model->nummodelsurfaces;i++)
11258         {
11259                 j = model->sortedmodelsurfaces[i];
11260                 if (r_refdef.viewcache.world_surfacevisible[j])
11261                         r_surfacelist[numsurfacelist++] = surfaces + j;
11262         }
11263         // update lightmaps if needed
11264         if (model->brushq1.firstrender)
11265         {
11266                 model->brushq1.firstrender = false;
11267                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11268                         if (update[j])
11269                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11270         }
11271         else if (update)
11272         {
11273                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11274                         if (r_refdef.viewcache.world_surfacevisible[j])
11275                                 if (update[j])
11276                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11277         }
11278         // don't do anything if there were no surfaces
11279         if (!numsurfacelist)
11280         {
11281                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11282                 return;
11283         }
11284         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11285
11286         // add to stats if desired
11287         if (r_speeds.integer && !skysurfaces && !depthonly)
11288         {
11289                 r_refdef.stats.world_surfaces += numsurfacelist;
11290                 for (j = 0;j < numsurfacelist;j++)
11291                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11292         }
11293
11294         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11295 }
11296
11297 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11298 {
11299         int i, j, endj, flagsmask;
11300         dp_model_t *model = ent->model;
11301         msurface_t *surfaces;
11302         unsigned char *update;
11303         int numsurfacelist = 0;
11304         if (model == NULL)
11305                 return;
11306
11307         if (r_maxsurfacelist < model->num_surfaces)
11308         {
11309                 r_maxsurfacelist = model->num_surfaces;
11310                 if (r_surfacelist)
11311                         Mem_Free((msurface_t **)r_surfacelist);
11312                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11313         }
11314
11315         // if the model is static it doesn't matter what value we give for
11316         // wantnormals and wanttangents, so this logic uses only rules applicable
11317         // to a model, knowing that they are meaningless otherwise
11318         if (ent == r_refdef.scene.worldentity)
11319                 RSurf_ActiveWorldEntity();
11320         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11321                 RSurf_ActiveModelEntity(ent, false, false, false);
11322         else if (prepass)
11323                 RSurf_ActiveModelEntity(ent, true, true, true);
11324         else if (depthonly)
11325         {
11326                 switch (vid.renderpath)
11327                 {
11328                 case RENDERPATH_GL20:
11329                 case RENDERPATH_D3D9:
11330                 case RENDERPATH_D3D10:
11331                 case RENDERPATH_D3D11:
11332                 case RENDERPATH_SOFT:
11333                 case RENDERPATH_GLES2:
11334                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11335                         break;
11336                 case RENDERPATH_GL13:
11337                 case RENDERPATH_GL11:
11338                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11339                         break;
11340                 }
11341         }
11342         else
11343         {
11344                 switch (vid.renderpath)
11345                 {
11346                 case RENDERPATH_GL20:
11347                 case RENDERPATH_D3D9:
11348                 case RENDERPATH_D3D10:
11349                 case RENDERPATH_D3D11:
11350                 case RENDERPATH_SOFT:
11351                 case RENDERPATH_GLES2:
11352                         RSurf_ActiveModelEntity(ent, true, true, false);
11353                         break;
11354                 case RENDERPATH_GL13:
11355                 case RENDERPATH_GL11:
11356                         RSurf_ActiveModelEntity(ent, true, false, false);
11357                         break;
11358                 }
11359         }
11360
11361         surfaces = model->data_surfaces;
11362         update = model->brushq1.lightmapupdateflags;
11363
11364         // update light styles
11365         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11366         {
11367                 model_brush_lightstyleinfo_t *style;
11368                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11369                 {
11370                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11371                         {
11372                                 int *list = style->surfacelist;
11373                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11374                                 for (j = 0;j < style->numsurfaces;j++)
11375                                         update[list[j]] = true;
11376                         }
11377                 }
11378         }
11379
11380         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11381
11382         if (debug)
11383         {
11384                 R_DrawDebugModel();
11385                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11386                 return;
11387         }
11388
11389         rsurface.lightmaptexture = NULL;
11390         rsurface.deluxemaptexture = NULL;
11391         rsurface.uselightmaptexture = false;
11392         rsurface.texture = NULL;
11393         rsurface.rtlight = NULL;
11394         numsurfacelist = 0;
11395         // add visible surfaces to draw list
11396         for (i = 0;i < model->nummodelsurfaces;i++)
11397                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11398         // don't do anything if there were no surfaces
11399         if (!numsurfacelist)
11400         {
11401                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11402                 return;
11403         }
11404         // update lightmaps if needed
11405         if (update)
11406         {
11407                 int updated = 0;
11408                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11409                 {
11410                         if (update[j])
11411                         {
11412                                 updated++;
11413                                 R_BuildLightMap(ent, surfaces + j);
11414                         }
11415                 }
11416         }
11417         if (update)
11418                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11419                         if (update[j])
11420                                 R_BuildLightMap(ent, surfaces + j);
11421         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11422
11423         // add to stats if desired
11424         if (r_speeds.integer && !skysurfaces && !depthonly)
11425         {
11426                 r_refdef.stats.entities_surfaces += numsurfacelist;
11427                 for (j = 0;j < numsurfacelist;j++)
11428                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11429         }
11430
11431         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11432 }
11433
11434 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11435 {
11436         static texture_t texture;
11437         static msurface_t surface;
11438         const msurface_t *surfacelist = &surface;
11439
11440         // fake enough texture and surface state to render this geometry
11441
11442         texture.update_lastrenderframe = -1; // regenerate this texture
11443         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11444         texture.currentskinframe = skinframe;
11445         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11446         texture.offsetmapping = OFFSETMAPPING_OFF;
11447         texture.offsetscale = 1;
11448         texture.specularscalemod = 1;
11449         texture.specularpowermod = 1;
11450
11451         surface.texture = &texture;
11452         surface.num_triangles = numtriangles;
11453         surface.num_firsttriangle = firsttriangle;
11454         surface.num_vertices = numvertices;
11455         surface.num_firstvertex = firstvertex;
11456
11457         // now render it
11458         rsurface.texture = R_GetCurrentTexture(surface.texture);
11459         rsurface.lightmaptexture = NULL;
11460         rsurface.deluxemaptexture = NULL;
11461         rsurface.uselightmaptexture = false;
11462         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11463 }
11464
11465 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)
11466 {
11467         static msurface_t surface;
11468         const msurface_t *surfacelist = &surface;
11469
11470         // fake enough texture and surface state to render this geometry
11471         surface.texture = texture;
11472         surface.num_triangles = numtriangles;
11473         surface.num_firsttriangle = firsttriangle;
11474         surface.num_vertices = numvertices;
11475         surface.num_firstvertex = firstvertex;
11476
11477         // now render it
11478         rsurface.texture = R_GetCurrentTexture(surface.texture);
11479         rsurface.lightmaptexture = NULL;
11480         rsurface.deluxemaptexture = NULL;
11481         rsurface.uselightmaptexture = false;
11482         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11483 }