]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix bug with iqm models by removing pose 0 optimization (as it
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
76 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
77 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
78 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
79 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
80 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
81 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
82 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
83 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
84 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
85 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
86 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
87 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
88 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
89 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
90 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
91 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
92 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
93 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
94 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
95 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
96 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
97 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
98 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
99
100 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
101 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
102 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
103
104 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
105 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
106 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
107 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
108 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
109 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
110 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
111 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
112 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
113 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
114 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
115 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
116 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
117 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
118 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
119 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
121 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
122 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
123 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
124 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
125 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
126
127 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
128 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
129 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
130 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
131 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
132 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
133 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
134 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
135
136 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)"};
137 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"};
138
139 cvar_t r_texture_sRGB_2d = {0, "r_texture_sRGB_2d", "0", "load textures as sRGB"};
140 cvar_t r_texture_sRGB_skin_diffuse = {0, "r_texture_sRGB_skin_diffuse", "0", "load textures as sRGB"};
141 cvar_t r_texture_sRGB_skin_gloss = {0, "r_texture_sRGB_skin_gloss", "0", "load textures as sRGB"};
142 cvar_t r_texture_sRGB_skin_glow = {0, "r_texture_sRGB_skin_glow", "0", "load textures as sRGB"};
143 cvar_t r_texture_sRGB_skin_reflect = {0, "r_texture_sRGB_skin_reflect", "0", "load textures as sRGB"};
144 cvar_t r_texture_sRGB_cubemap = {0, "r_texture_sRGB_cubemap", "0", "load textures as sRGB"};
145 cvar_t r_texture_sRGB_skybox = {0, "r_texture_sRGB_skybox", "0", "load textures as sRGB"};
146
147 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
148 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
149 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
150
151 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"};
152 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"};
153 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
154 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
155 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"};
156 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)"};
157 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)"};
158 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
159
160 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)"};
161 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
162 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)"};
163 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
164 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)"};
165 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)"};
166 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
167 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
176
177 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)"};
178 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
179 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"};
180 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
181 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
182 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
183
184 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
185 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
186 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
187 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
188
189 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
190 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
191 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
192 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
193 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
194 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
195 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
196
197 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
198 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
199 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
200 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)"};
201 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
202 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
203 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
204 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
205 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
206 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
207
208 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"};
209
210 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"};
211
212 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
213
214 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
215 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"};
216 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
217 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
218 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
219 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
220 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)"};
221 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
222 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
223
224 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
225 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"};
226
227 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."};
228
229 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)"};
230
231 extern cvar_t v_glslgamma;
232
233 extern qboolean v_flipped_state;
234
235 static struct r_bloomstate_s
236 {
237         qboolean enabled;
238         qboolean hdr;
239
240         int bloomwidth, bloomheight;
241
242         textype_t texturetype;
243         int viewfbo; // used to check if r_viewfbo cvar has changed
244
245         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
246         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
247         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
248
249         int screentexturewidth, screentextureheight;
250         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
251
252         int bloomtexturewidth, bloomtextureheight;
253         rtexture_t *texture_bloom;
254
255         // arrays for rendering the screen passes
256         float screentexcoord2f[8];
257         float bloomtexcoord2f[8];
258         float offsettexcoord2f[8];
259
260         r_viewport_t viewport;
261 }
262 r_bloomstate;
263
264 r_waterstate_t r_waterstate;
265
266 /// shadow volume bsp struct with automatically growing nodes buffer
267 svbsp_t r_svbsp;
268
269 rtexture_t *r_texture_blanknormalmap;
270 rtexture_t *r_texture_white;
271 rtexture_t *r_texture_grey128;
272 rtexture_t *r_texture_black;
273 rtexture_t *r_texture_notexture;
274 rtexture_t *r_texture_whitecube;
275 rtexture_t *r_texture_normalizationcube;
276 rtexture_t *r_texture_fogattenuation;
277 rtexture_t *r_texture_fogheighttexture;
278 rtexture_t *r_texture_gammaramps;
279 unsigned int r_texture_gammaramps_serial;
280 //rtexture_t *r_texture_fogintensity;
281 rtexture_t *r_texture_reflectcube;
282
283 // TODO: hash lookups?
284 typedef struct cubemapinfo_s
285 {
286         char basename[64];
287         rtexture_t *texture;
288 }
289 cubemapinfo_t;
290
291 int r_texture_numcubemaps;
292 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
293
294 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
295 unsigned int r_numqueries;
296 unsigned int r_maxqueries;
297
298 typedef struct r_qwskincache_s
299 {
300         char name[MAX_QPATH];
301         skinframe_t *skinframe;
302 }
303 r_qwskincache_t;
304
305 static r_qwskincache_t *r_qwskincache;
306 static int r_qwskincache_size;
307
308 /// vertex coordinates for a quad that covers the screen exactly
309 extern const float r_screenvertex3f[12];
310 extern const float r_d3dscreenvertex3f[12];
311 const float r_screenvertex3f[12] =
312 {
313         0, 0, 0,
314         1, 0, 0,
315         1, 1, 0,
316         0, 1, 0
317 };
318 const float r_d3dscreenvertex3f[12] =
319 {
320         0, 1, 0,
321         1, 1, 0,
322         1, 0, 0,
323         0, 0, 0
324 };
325
326 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
327 {
328         int i;
329         for (i = 0;i < verts;i++)
330         {
331                 out[0] = in[0] * r;
332                 out[1] = in[1] * g;
333                 out[2] = in[2] * b;
334                 out[3] = in[3];
335                 in += 4;
336                 out += 4;
337         }
338 }
339
340 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
341 {
342         int i;
343         for (i = 0;i < verts;i++)
344         {
345                 out[0] = r;
346                 out[1] = g;
347                 out[2] = b;
348                 out[3] = a;
349                 out += 4;
350         }
351 }
352
353 // FIXME: move this to client?
354 void FOG_clear(void)
355 {
356         if (gamemode == GAME_NEHAHRA)
357         {
358                 Cvar_Set("gl_fogenable", "0");
359                 Cvar_Set("gl_fogdensity", "0.2");
360                 Cvar_Set("gl_fogred", "0.3");
361                 Cvar_Set("gl_foggreen", "0.3");
362                 Cvar_Set("gl_fogblue", "0.3");
363         }
364         r_refdef.fog_density = 0;
365         r_refdef.fog_red = 0;
366         r_refdef.fog_green = 0;
367         r_refdef.fog_blue = 0;
368         r_refdef.fog_alpha = 1;
369         r_refdef.fog_start = 0;
370         r_refdef.fog_end = 16384;
371         r_refdef.fog_height = 1<<30;
372         r_refdef.fog_fadedepth = 128;
373         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
374 }
375
376 static void R_BuildBlankTextures(void)
377 {
378         unsigned char data[4];
379         data[2] = 128; // normal X
380         data[1] = 128; // normal Y
381         data[0] = 255; // normal Z
382         data[3] = 128; // height
383         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384         data[0] = 255;
385         data[1] = 255;
386         data[2] = 255;
387         data[3] = 255;
388         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
389         data[0] = 128;
390         data[1] = 128;
391         data[2] = 128;
392         data[3] = 255;
393         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
394         data[0] = 0;
395         data[1] = 0;
396         data[2] = 0;
397         data[3] = 255;
398         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
399 }
400
401 static void R_BuildNoTexture(void)
402 {
403         int x, y;
404         unsigned char pix[16][16][4];
405         // this makes a light grey/dark grey checkerboard texture
406         for (y = 0;y < 16;y++)
407         {
408                 for (x = 0;x < 16;x++)
409                 {
410                         if ((y < 8) ^ (x < 8))
411                         {
412                                 pix[y][x][0] = 128;
413                                 pix[y][x][1] = 128;
414                                 pix[y][x][2] = 128;
415                                 pix[y][x][3] = 255;
416                         }
417                         else
418                         {
419                                 pix[y][x][0] = 64;
420                                 pix[y][x][1] = 64;
421                                 pix[y][x][2] = 64;
422                                 pix[y][x][3] = 255;
423                         }
424                 }
425         }
426         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
427 }
428
429 static void R_BuildWhiteCube(void)
430 {
431         unsigned char data[6*1*1*4];
432         memset(data, 255, sizeof(data));
433         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
434 }
435
436 static void R_BuildNormalizationCube(void)
437 {
438         int x, y, side;
439         vec3_t v;
440         vec_t s, t, intensity;
441 #define NORMSIZE 64
442         unsigned char *data;
443         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
444         for (side = 0;side < 6;side++)
445         {
446                 for (y = 0;y < NORMSIZE;y++)
447                 {
448                         for (x = 0;x < NORMSIZE;x++)
449                         {
450                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
451                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
452                                 switch(side)
453                                 {
454                                 default:
455                                 case 0:
456                                         v[0] = 1;
457                                         v[1] = -t;
458                                         v[2] = -s;
459                                         break;
460                                 case 1:
461                                         v[0] = -1;
462                                         v[1] = -t;
463                                         v[2] = s;
464                                         break;
465                                 case 2:
466                                         v[0] = s;
467                                         v[1] = 1;
468                                         v[2] = t;
469                                         break;
470                                 case 3:
471                                         v[0] = s;
472                                         v[1] = -1;
473                                         v[2] = -t;
474                                         break;
475                                 case 4:
476                                         v[0] = s;
477                                         v[1] = -t;
478                                         v[2] = 1;
479                                         break;
480                                 case 5:
481                                         v[0] = -s;
482                                         v[1] = -t;
483                                         v[2] = -1;
484                                         break;
485                                 }
486                                 intensity = 127.0f / sqrt(DotProduct(v, v));
487                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
488                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
489                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
490                                 data[((side*64+y)*64+x)*4+3] = 255;
491                         }
492                 }
493         }
494         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
495         Mem_Free(data);
496 }
497
498 static void R_BuildFogTexture(void)
499 {
500         int x, b;
501 #define FOGWIDTH 256
502         unsigned char data1[FOGWIDTH][4];
503         //unsigned char data2[FOGWIDTH][4];
504         double d, r, alpha;
505
506         r_refdef.fogmasktable_start = r_refdef.fog_start;
507         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
508         r_refdef.fogmasktable_range = r_refdef.fogrange;
509         r_refdef.fogmasktable_density = r_refdef.fog_density;
510
511         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
512         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
513         {
514                 d = (x * r - r_refdef.fogmasktable_start);
515                 if(developer_extra.integer)
516                         Con_DPrintf("%f ", d);
517                 d = max(0, d);
518                 if (r_fog_exp2.integer)
519                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
520                 else
521                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
522                 if(developer_extra.integer)
523                         Con_DPrintf(" : %f ", alpha);
524                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
525                 if(developer_extra.integer)
526                         Con_DPrintf(" = %f\n", alpha);
527                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
528         }
529
530         for (x = 0;x < FOGWIDTH;x++)
531         {
532                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
533                 data1[x][0] = b;
534                 data1[x][1] = b;
535                 data1[x][2] = b;
536                 data1[x][3] = 255;
537                 //data2[x][0] = 255 - b;
538                 //data2[x][1] = 255 - b;
539                 //data2[x][2] = 255 - b;
540                 //data2[x][3] = 255;
541         }
542         if (r_texture_fogattenuation)
543         {
544                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
545                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
546         }
547         else
548         {
549                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
550                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
551         }
552 }
553
554 static void R_BuildFogHeightTexture(void)
555 {
556         unsigned char *inpixels;
557         int size;
558         int x;
559         int y;
560         int j;
561         float c[4];
562         float f;
563         inpixels = NULL;
564         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
565         if (r_refdef.fogheighttexturename[0])
566                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
567         if (!inpixels)
568         {
569                 r_refdef.fog_height_tablesize = 0;
570                 if (r_texture_fogheighttexture)
571                         R_FreeTexture(r_texture_fogheighttexture);
572                 r_texture_fogheighttexture = NULL;
573                 if (r_refdef.fog_height_table2d)
574                         Mem_Free(r_refdef.fog_height_table2d);
575                 r_refdef.fog_height_table2d = NULL;
576                 if (r_refdef.fog_height_table1d)
577                         Mem_Free(r_refdef.fog_height_table1d);
578                 r_refdef.fog_height_table1d = NULL;
579                 return;
580         }
581         size = image_width;
582         r_refdef.fog_height_tablesize = size;
583         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
584         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
585         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
586         Mem_Free(inpixels);
587         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
588         // average fog color table accounting for every fog layer between a point
589         // and the camera.  (Note: attenuation is handled separately!)
590         for (y = 0;y < size;y++)
591         {
592                 for (x = 0;x < size;x++)
593                 {
594                         Vector4Clear(c);
595                         f = 0;
596                         if (x < y)
597                         {
598                                 for (j = x;j <= y;j++)
599                                 {
600                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
601                                         f++;
602                                 }
603                         }
604                         else
605                         {
606                                 for (j = x;j >= y;j--)
607                                 {
608                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
609                                         f++;
610                                 }
611                         }
612                         f = 1.0f / f;
613                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
614                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
615                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
616                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
617                 }
618         }
619         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
620 }
621
622 //=======================================================================================================================================================
623
624 static const char *builtinshaderstring =
625 #include "shader_glsl.h"
626 ;
627
628 const char *builtinhlslshaderstring =
629 #include "shader_hlsl.h"
630 ;
631
632 char *glslshaderstring = NULL;
633 char *hlslshaderstring = NULL;
634
635 //=======================================================================================================================================================
636
637 typedef struct shaderpermutationinfo_s
638 {
639         const char *pretext;
640         const char *name;
641 }
642 shaderpermutationinfo_t;
643
644 typedef struct shadermodeinfo_s
645 {
646         const char *vertexfilename;
647         const char *geometryfilename;
648         const char *fragmentfilename;
649         const char *pretext;
650         const char *name;
651 }
652 shadermodeinfo_t;
653
654 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
655 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
656 {
657         {"#define USEDIFFUSE\n", " diffuse"},
658         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
659         {"#define USEVIEWTINT\n", " viewtint"},
660         {"#define USECOLORMAPPING\n", " colormapping"},
661         {"#define USESATURATION\n", " saturation"},
662         {"#define USEFOGINSIDE\n", " foginside"},
663         {"#define USEFOGOUTSIDE\n", " fogoutside"},
664         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
665         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
666         {"#define USEGAMMARAMPS\n", " gammaramps"},
667         {"#define USECUBEFILTER\n", " cubefilter"},
668         {"#define USEGLOW\n", " glow"},
669         {"#define USEBLOOM\n", " bloom"},
670         {"#define USESPECULAR\n", " specular"},
671         {"#define USEPOSTPROCESSING\n", " postprocessing"},
672         {"#define USEREFLECTION\n", " reflection"},
673         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
674         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
675         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
676         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
677         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
678         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
679         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
680         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
681         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
682         {"#define USEALPHAKILL\n", " alphakill"},
683         {"#define USEREFLECTCUBE\n", " reflectcube"},
684         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
685         {"#define USEBOUNCEGRID\n", " bouncegrid"},
686         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
687 };
688
689 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
690 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
691 {
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
694         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
704         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
705         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
706         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
707         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
708 };
709
710 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
711 {
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
725         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
726         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
727         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
728 };
729
730 struct r_glsl_permutation_s;
731 typedef struct r_glsl_permutation_s
732 {
733         /// hash lookup data
734         struct r_glsl_permutation_s *hashnext;
735         unsigned int mode;
736         unsigned int permutation;
737
738         /// indicates if we have tried compiling this permutation already
739         qboolean compiled;
740         /// 0 if compilation failed
741         int program;
742         // texture units assigned to each detected uniform
743         int tex_Texture_First;
744         int tex_Texture_Second;
745         int tex_Texture_GammaRamps;
746         int tex_Texture_Normal;
747         int tex_Texture_Color;
748         int tex_Texture_Gloss;
749         int tex_Texture_Glow;
750         int tex_Texture_SecondaryNormal;
751         int tex_Texture_SecondaryColor;
752         int tex_Texture_SecondaryGloss;
753         int tex_Texture_SecondaryGlow;
754         int tex_Texture_Pants;
755         int tex_Texture_Shirt;
756         int tex_Texture_FogHeightTexture;
757         int tex_Texture_FogMask;
758         int tex_Texture_Lightmap;
759         int tex_Texture_Deluxemap;
760         int tex_Texture_Attenuation;
761         int tex_Texture_Cube;
762         int tex_Texture_Refraction;
763         int tex_Texture_Reflection;
764         int tex_Texture_ShadowMap2D;
765         int tex_Texture_CubeProjection;
766         int tex_Texture_ScreenDepth;
767         int tex_Texture_ScreenNormalMap;
768         int tex_Texture_ScreenDiffuse;
769         int tex_Texture_ScreenSpecular;
770         int tex_Texture_ReflectMask;
771         int tex_Texture_ReflectCube;
772         int tex_Texture_BounceGrid;
773         /// locations of detected uniforms in program object, or -1 if not found
774         int loc_Texture_First;
775         int loc_Texture_Second;
776         int loc_Texture_GammaRamps;
777         int loc_Texture_Normal;
778         int loc_Texture_Color;
779         int loc_Texture_Gloss;
780         int loc_Texture_Glow;
781         int loc_Texture_SecondaryNormal;
782         int loc_Texture_SecondaryColor;
783         int loc_Texture_SecondaryGloss;
784         int loc_Texture_SecondaryGlow;
785         int loc_Texture_Pants;
786         int loc_Texture_Shirt;
787         int loc_Texture_FogHeightTexture;
788         int loc_Texture_FogMask;
789         int loc_Texture_Lightmap;
790         int loc_Texture_Deluxemap;
791         int loc_Texture_Attenuation;
792         int loc_Texture_Cube;
793         int loc_Texture_Refraction;
794         int loc_Texture_Reflection;
795         int loc_Texture_ShadowMap2D;
796         int loc_Texture_CubeProjection;
797         int loc_Texture_ScreenDepth;
798         int loc_Texture_ScreenNormalMap;
799         int loc_Texture_ScreenDiffuse;
800         int loc_Texture_ScreenSpecular;
801         int loc_Texture_ReflectMask;
802         int loc_Texture_ReflectCube;
803         int loc_Texture_BounceGrid;
804         int loc_Alpha;
805         int loc_BloomBlur_Parameters;
806         int loc_ClientTime;
807         int loc_Color_Ambient;
808         int loc_Color_Diffuse;
809         int loc_Color_Specular;
810         int loc_Color_Glow;
811         int loc_Color_Pants;
812         int loc_Color_Shirt;
813         int loc_DeferredColor_Ambient;
814         int loc_DeferredColor_Diffuse;
815         int loc_DeferredColor_Specular;
816         int loc_DeferredMod_Diffuse;
817         int loc_DeferredMod_Specular;
818         int loc_DistortScaleRefractReflect;
819         int loc_EyePosition;
820         int loc_FogColor;
821         int loc_FogHeightFade;
822         int loc_FogPlane;
823         int loc_FogPlaneViewDist;
824         int loc_FogRangeRecip;
825         int loc_LightColor;
826         int loc_LightDir;
827         int loc_LightPosition;
828         int loc_OffsetMapping_ScaleSteps;
829         int loc_PixelSize;
830         int loc_ReflectColor;
831         int loc_ReflectFactor;
832         int loc_ReflectOffset;
833         int loc_RefractColor;
834         int loc_Saturation;
835         int loc_ScreenCenterRefractReflect;
836         int loc_ScreenScaleRefractReflect;
837         int loc_ScreenToDepth;
838         int loc_ShadowMap_Parameters;
839         int loc_ShadowMap_TextureScale;
840         int loc_SpecularPower;
841         int loc_UserVec1;
842         int loc_UserVec2;
843         int loc_UserVec3;
844         int loc_UserVec4;
845         int loc_ViewTintColor;
846         int loc_ViewToLight;
847         int loc_ModelToLight;
848         int loc_TexMatrix;
849         int loc_BackgroundTexMatrix;
850         int loc_ModelViewProjectionMatrix;
851         int loc_ModelViewMatrix;
852         int loc_PixelToScreenTexCoord;
853         int loc_ModelToReflectCube;
854         int loc_ShadowMapMatrix;
855         int loc_BloomColorSubtract;
856         int loc_NormalmapScrollBlend;
857         int loc_BounceGridMatrix;
858         int loc_BounceGridIntensity;
859 }
860 r_glsl_permutation_t;
861
862 #define SHADERPERMUTATION_HASHSIZE 256
863
864
865 // non-degradable "lightweight" shader parameters to keep the permutations simpler
866 // these can NOT degrade! only use for simple stuff
867 enum
868 {
869         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
870         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
871         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
872         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
873         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
874         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
875         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
876 };
877 #define SHADERSTATICPARMS_COUNT 7
878
879 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
880 static int shaderstaticparms_count = 0;
881
882 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
883 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
884 qboolean R_CompileShader_CheckStaticParms(void)
885 {
886         static int r_compileshader_staticparms_save[1];
887         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
888         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
889
890         // detect all
891         if (r_glsl_saturation_redcompensate.integer)
892                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
893         if (r_glsl_vertextextureblend_usebothalphas.integer)
894                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
895         if (r_shadow_glossexact.integer)
896                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
897         if (r_glsl_postprocess.integer)
898         {
899                 if (r_glsl_postprocess_uservec1_enable.integer)
900                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
901                 if (r_glsl_postprocess_uservec2_enable.integer)
902                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
903                 if (r_glsl_postprocess_uservec3_enable.integer)
904                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
905                 if (r_glsl_postprocess_uservec4_enable.integer)
906                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
907         }
908         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
909 }
910
911 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
912         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
913                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
914         else \
915                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
916 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
917 {
918         shaderstaticparms_count = 0;
919
920         // emit all
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
925         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
926         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
928 }
929
930 /// information about each possible shader permutation
931 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
932 /// currently selected permutation
933 r_glsl_permutation_t *r_glsl_permutation;
934 /// storage for permutations linked in the hash table
935 memexpandablearray_t r_glsl_permutationarray;
936
937 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
938 {
939         //unsigned int hashdepth = 0;
940         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
941         r_glsl_permutation_t *p;
942         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
943         {
944                 if (p->mode == mode && p->permutation == permutation)
945                 {
946                         //if (hashdepth > 10)
947                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
948                         return p;
949                 }
950                 //hashdepth++;
951         }
952         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
953         p->mode = mode;
954         p->permutation = permutation;
955         p->hashnext = r_glsl_permutationhash[mode][hashindex];
956         r_glsl_permutationhash[mode][hashindex] = p;
957         //if (hashdepth > 10)
958         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
959         return p;
960 }
961
962 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
963 {
964         char *shaderstring;
965         if (!filename || !filename[0])
966                 return NULL;
967         if (!strcmp(filename, "glsl/default.glsl"))
968         {
969                 if (!glslshaderstring)
970                 {
971                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
972                         if (glslshaderstring)
973                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
974                         else
975                                 glslshaderstring = (char *)builtinshaderstring;
976                 }
977                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
978                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
979                 return shaderstring;
980         }
981         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
982         if (shaderstring)
983         {
984                 if (printfromdisknotice)
985                         Con_DPrintf("from disk %s... ", filename);
986                 return shaderstring;
987         }
988         return shaderstring;
989 }
990
991 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
992 {
993         int i;
994         int sampler;
995         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
996         char *vertexstring, *geometrystring, *fragmentstring;
997         char permutationname[256];
998         int vertstrings_count = 0;
999         int geomstrings_count = 0;
1000         int fragstrings_count = 0;
1001         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1002         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1003         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1004
1005         if (p->compiled)
1006                 return;
1007         p->compiled = true;
1008         p->program = 0;
1009
1010         permutationname[0] = 0;
1011         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1012         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1013         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1014
1015         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1016
1017         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1018         if(vid.support.gl20shaders130)
1019         {
1020                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1021                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1022                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1023                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1024                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1025                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1026         }
1027
1028         // the first pretext is which type of shader to compile as
1029         // (later these will all be bound together as a program object)
1030         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1031         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1032         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1033
1034         // the second pretext is the mode (for example a light source)
1035         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1036         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1037         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1038         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1039
1040         // now add all the permutation pretexts
1041         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1042         {
1043                 if (permutation & (1<<i))
1044                 {
1045                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1046                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1047                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1048                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1049                 }
1050                 else
1051                 {
1052                         // keep line numbers correct
1053                         vertstrings_list[vertstrings_count++] = "\n";
1054                         geomstrings_list[geomstrings_count++] = "\n";
1055                         fragstrings_list[fragstrings_count++] = "\n";
1056                 }
1057         }
1058
1059         // add static parms
1060         R_CompileShader_AddStaticParms(mode, permutation);
1061         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1062         vertstrings_count += shaderstaticparms_count;
1063         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1064         geomstrings_count += shaderstaticparms_count;
1065         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1066         fragstrings_count += shaderstaticparms_count;
1067
1068         // now append the shader text itself
1069         vertstrings_list[vertstrings_count++] = vertexstring;
1070         geomstrings_list[geomstrings_count++] = geometrystring;
1071         fragstrings_list[fragstrings_count++] = fragmentstring;
1072
1073         // if any sources were NULL, clear the respective list
1074         if (!vertexstring)
1075                 vertstrings_count = 0;
1076         if (!geometrystring)
1077                 geomstrings_count = 0;
1078         if (!fragmentstring)
1079                 fragstrings_count = 0;
1080
1081         // compile the shader program
1082         if (vertstrings_count + geomstrings_count + fragstrings_count)
1083                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1084         if (p->program)
1085         {
1086                 CHECKGLERROR
1087                 qglUseProgram(p->program);CHECKGLERROR
1088                 // look up all the uniform variable names we care about, so we don't
1089                 // have to look them up every time we set them
1090
1091                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1092                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1093                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1094                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1095                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1096                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1097                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1098                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1099                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1100                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1101                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1102                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1103                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1104                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1105                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1106                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1107                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1108                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1109                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1110                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1111                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1112                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1113                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1114                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1115                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1116                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1117                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1118                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1119                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1120                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1121                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1122                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1123                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1124                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1125                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1126                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1127                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1128                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1129                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1130                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1131                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1132                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1133                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1134                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1135                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1136                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1137                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1138                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1139                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1140                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1141                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1142                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1143                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1144                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1145                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1146                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1147                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1148                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1149                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1150                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1151                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1152                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1153                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1154                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1155                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1156                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1157                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1158                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1159                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1160                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1161                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1162                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1163                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1164                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1165                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1166                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1167                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1168                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1169                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1170                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1171                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1172                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1173                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1174                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1175                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1176                 // initialize the samplers to refer to the texture units we use
1177                 p->tex_Texture_First = -1;
1178                 p->tex_Texture_Second = -1;
1179                 p->tex_Texture_GammaRamps = -1;
1180                 p->tex_Texture_Normal = -1;
1181                 p->tex_Texture_Color = -1;
1182                 p->tex_Texture_Gloss = -1;
1183                 p->tex_Texture_Glow = -1;
1184                 p->tex_Texture_SecondaryNormal = -1;
1185                 p->tex_Texture_SecondaryColor = -1;
1186                 p->tex_Texture_SecondaryGloss = -1;
1187                 p->tex_Texture_SecondaryGlow = -1;
1188                 p->tex_Texture_Pants = -1;
1189                 p->tex_Texture_Shirt = -1;
1190                 p->tex_Texture_FogHeightTexture = -1;
1191                 p->tex_Texture_FogMask = -1;
1192                 p->tex_Texture_Lightmap = -1;
1193                 p->tex_Texture_Deluxemap = -1;
1194                 p->tex_Texture_Attenuation = -1;
1195                 p->tex_Texture_Cube = -1;
1196                 p->tex_Texture_Refraction = -1;
1197                 p->tex_Texture_Reflection = -1;
1198                 p->tex_Texture_ShadowMap2D = -1;
1199                 p->tex_Texture_CubeProjection = -1;
1200                 p->tex_Texture_ScreenDepth = -1;
1201                 p->tex_Texture_ScreenNormalMap = -1;
1202                 p->tex_Texture_ScreenDiffuse = -1;
1203                 p->tex_Texture_ScreenSpecular = -1;
1204                 p->tex_Texture_ReflectMask = -1;
1205                 p->tex_Texture_ReflectCube = -1;
1206                 p->tex_Texture_BounceGrid = -1;
1207                 sampler = 0;
1208                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1209                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1210                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1211                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1212                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1213                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1214                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1215                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1216                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1217                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1218                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1219                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1220                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1221                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1222                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1223                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1224                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1225                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1226                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1227                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1228                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1229                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1230                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1231                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1232                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1233                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1234                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1235                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1236                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1237                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1238                 CHECKGLERROR
1239                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1240         }
1241         else
1242                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1243
1244         // free the strings
1245         if (vertexstring)
1246                 Mem_Free(vertexstring);
1247         if (geometrystring)
1248                 Mem_Free(geometrystring);
1249         if (fragmentstring)
1250                 Mem_Free(fragmentstring);
1251 }
1252
1253 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1254 {
1255         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1256         if (r_glsl_permutation != perm)
1257         {
1258                 r_glsl_permutation = perm;
1259                 if (!r_glsl_permutation->program)
1260                 {
1261                         if (!r_glsl_permutation->compiled)
1262                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1263                         if (!r_glsl_permutation->program)
1264                         {
1265                                 // remove features until we find a valid permutation
1266                                 int i;
1267                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1268                                 {
1269                                         // reduce i more quickly whenever it would not remove any bits
1270                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1271                                         if (!(permutation & j))
1272                                                 continue;
1273                                         permutation -= j;
1274                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1275                                         if (!r_glsl_permutation->compiled)
1276                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1277                                         if (r_glsl_permutation->program)
1278                                                 break;
1279                                 }
1280                                 if (i >= SHADERPERMUTATION_COUNT)
1281                                 {
1282                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1283                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1284                                         qglUseProgram(0);CHECKGLERROR
1285                                         return; // no bit left to clear, entire mode is broken
1286                                 }
1287                         }
1288                 }
1289                 CHECKGLERROR
1290                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1291         }
1292         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1293         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1294         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1295 }
1296
1297 #ifdef SUPPORTD3D
1298
1299 #ifdef SUPPORTD3D
1300 #include <d3d9.h>
1301 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1302 extern D3DCAPS9 vid_d3d9caps;
1303 #endif
1304
1305 struct r_hlsl_permutation_s;
1306 typedef struct r_hlsl_permutation_s
1307 {
1308         /// hash lookup data
1309         struct r_hlsl_permutation_s *hashnext;
1310         unsigned int mode;
1311         unsigned int permutation;
1312
1313         /// indicates if we have tried compiling this permutation already
1314         qboolean compiled;
1315         /// NULL if compilation failed
1316         IDirect3DVertexShader9 *vertexshader;
1317         IDirect3DPixelShader9 *pixelshader;
1318 }
1319 r_hlsl_permutation_t;
1320
1321 typedef enum D3DVSREGISTER_e
1322 {
1323         D3DVSREGISTER_TexMatrix = 0, // float4x4
1324         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1325         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1326         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1327         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1328         D3DVSREGISTER_ModelToLight = 20, // float4x4
1329         D3DVSREGISTER_EyePosition = 24,
1330         D3DVSREGISTER_FogPlane = 25,
1331         D3DVSREGISTER_LightDir = 26,
1332         D3DVSREGISTER_LightPosition = 27,
1333 }
1334 D3DVSREGISTER_t;
1335
1336 typedef enum D3DPSREGISTER_e
1337 {
1338         D3DPSREGISTER_Alpha = 0,
1339         D3DPSREGISTER_BloomBlur_Parameters = 1,
1340         D3DPSREGISTER_ClientTime = 2,
1341         D3DPSREGISTER_Color_Ambient = 3,
1342         D3DPSREGISTER_Color_Diffuse = 4,
1343         D3DPSREGISTER_Color_Specular = 5,
1344         D3DPSREGISTER_Color_Glow = 6,
1345         D3DPSREGISTER_Color_Pants = 7,
1346         D3DPSREGISTER_Color_Shirt = 8,
1347         D3DPSREGISTER_DeferredColor_Ambient = 9,
1348         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1349         D3DPSREGISTER_DeferredColor_Specular = 11,
1350         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1351         D3DPSREGISTER_DeferredMod_Specular = 13,
1352         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1353         D3DPSREGISTER_EyePosition = 15, // unused
1354         D3DPSREGISTER_FogColor = 16,
1355         D3DPSREGISTER_FogHeightFade = 17,
1356         D3DPSREGISTER_FogPlane = 18,
1357         D3DPSREGISTER_FogPlaneViewDist = 19,
1358         D3DPSREGISTER_FogRangeRecip = 20,
1359         D3DPSREGISTER_LightColor = 21,
1360         D3DPSREGISTER_LightDir = 22, // unused
1361         D3DPSREGISTER_LightPosition = 23,
1362         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1363         D3DPSREGISTER_PixelSize = 25,
1364         D3DPSREGISTER_ReflectColor = 26,
1365         D3DPSREGISTER_ReflectFactor = 27,
1366         D3DPSREGISTER_ReflectOffset = 28,
1367         D3DPSREGISTER_RefractColor = 29,
1368         D3DPSREGISTER_Saturation = 30,
1369         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1370         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1371         D3DPSREGISTER_ScreenToDepth = 33,
1372         D3DPSREGISTER_ShadowMap_Parameters = 34,
1373         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1374         D3DPSREGISTER_SpecularPower = 36,
1375         D3DPSREGISTER_UserVec1 = 37,
1376         D3DPSREGISTER_UserVec2 = 38,
1377         D3DPSREGISTER_UserVec3 = 39,
1378         D3DPSREGISTER_UserVec4 = 40,
1379         D3DPSREGISTER_ViewTintColor = 41,
1380         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1381         D3DPSREGISTER_BloomColorSubtract = 43,
1382         D3DPSREGISTER_ViewToLight = 44, // float4x4
1383         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1384         D3DPSREGISTER_NormalmapScrollBlend = 52,
1385         // next at 53
1386 }
1387 D3DPSREGISTER_t;
1388
1389 /// information about each possible shader permutation
1390 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1391 /// currently selected permutation
1392 r_hlsl_permutation_t *r_hlsl_permutation;
1393 /// storage for permutations linked in the hash table
1394 memexpandablearray_t r_hlsl_permutationarray;
1395
1396 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1397 {
1398         //unsigned int hashdepth = 0;
1399         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1400         r_hlsl_permutation_t *p;
1401         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1402         {
1403                 if (p->mode == mode && p->permutation == permutation)
1404                 {
1405                         //if (hashdepth > 10)
1406                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1407                         return p;
1408                 }
1409                 //hashdepth++;
1410         }
1411         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1412         p->mode = mode;
1413         p->permutation = permutation;
1414         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1415         r_hlsl_permutationhash[mode][hashindex] = p;
1416         //if (hashdepth > 10)
1417         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1418         return p;
1419 }
1420
1421 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1422 {
1423         char *shaderstring;
1424         if (!filename || !filename[0])
1425                 return NULL;
1426         if (!strcmp(filename, "hlsl/default.hlsl"))
1427         {
1428                 if (!hlslshaderstring)
1429                 {
1430                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1431                         if (hlslshaderstring)
1432                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1433                         else
1434                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1435                 }
1436                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1437                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1438                 return shaderstring;
1439         }
1440         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1441         if (shaderstring)
1442         {
1443                 if (printfromdisknotice)
1444                         Con_DPrintf("from disk %s... ", filename);
1445                 return shaderstring;
1446         }
1447         return shaderstring;
1448 }
1449
1450 #include <d3dx9.h>
1451 //#include <d3dx9shader.h>
1452 //#include <d3dx9mesh.h>
1453
1454 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1455 {
1456         DWORD *vsbin = NULL;
1457         DWORD *psbin = NULL;
1458         fs_offset_t vsbinsize;
1459         fs_offset_t psbinsize;
1460 //      IDirect3DVertexShader9 *vs = NULL;
1461 //      IDirect3DPixelShader9 *ps = NULL;
1462         ID3DXBuffer *vslog = NULL;
1463         ID3DXBuffer *vsbuffer = NULL;
1464         ID3DXConstantTable *vsconstanttable = NULL;
1465         ID3DXBuffer *pslog = NULL;
1466         ID3DXBuffer *psbuffer = NULL;
1467         ID3DXConstantTable *psconstanttable = NULL;
1468         int vsresult = 0;
1469         int psresult = 0;
1470         char temp[MAX_INPUTLINE];
1471         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1472         qboolean debugshader = gl_paranoid.integer != 0;
1473         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1474         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1475         if (!debugshader)
1476         {
1477                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1478                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1479         }
1480         if ((!vsbin && vertstring) || (!psbin && fragstring))
1481         {
1482                 const char* dllnames_d3dx9 [] =
1483                 {
1484                         "d3dx9_43.dll",
1485                         "d3dx9_42.dll",
1486                         "d3dx9_41.dll",
1487                         "d3dx9_40.dll",
1488                         "d3dx9_39.dll",
1489                         "d3dx9_38.dll",
1490                         "d3dx9_37.dll",
1491                         "d3dx9_36.dll",
1492                         "d3dx9_35.dll",
1493                         "d3dx9_34.dll",
1494                         "d3dx9_33.dll",
1495                         "d3dx9_32.dll",
1496                         "d3dx9_31.dll",
1497                         "d3dx9_30.dll",
1498                         "d3dx9_29.dll",
1499                         "d3dx9_28.dll",
1500                         "d3dx9_27.dll",
1501                         "d3dx9_26.dll",
1502                         "d3dx9_25.dll",
1503                         "d3dx9_24.dll",
1504                         NULL
1505                 };
1506                 dllhandle_t d3dx9_dll = NULL;
1507                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1508                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1509                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1510                 dllfunction_t d3dx9_dllfuncs[] =
1511                 {
1512                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1513                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1514                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1515                         {NULL, NULL}
1516                 };
1517                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1518                 {
1519                         DWORD shaderflags = 0;
1520                         if (debugshader)
1521                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1522                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1523                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1524                         if (vertstring && vertstring[0])
1525                         {
1526                                 if (debugshader)
1527                                 {
1528 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1529 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1530                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1531                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1532                                 }
1533                                 else
1534                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1535                                 if (vsbuffer)
1536                                 {
1537                                         vsbinsize = vsbuffer->GetBufferSize();
1538                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1539                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1540                                         vsbuffer->Release();
1541                                 }
1542                                 if (vslog)
1543                                 {
1544                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1545                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1546                                         vslog->Release();
1547                                 }
1548                         }
1549                         if (fragstring && fragstring[0])
1550                         {
1551                                 if (debugshader)
1552                                 {
1553 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1554 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1555                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1556                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1557                                 }
1558                                 else
1559                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1560                                 if (psbuffer)
1561                                 {
1562                                         psbinsize = psbuffer->GetBufferSize();
1563                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1564                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1565                                         psbuffer->Release();
1566                                 }
1567                                 if (pslog)
1568                                 {
1569                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1570                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1571                                         pslog->Release();
1572                                 }
1573                         }
1574                         Sys_UnloadLibrary(&d3dx9_dll);
1575                 }
1576                 else
1577                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1578         }
1579         if (vsbin && psbin)
1580         {
1581                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1582                 if (FAILED(vsresult))
1583                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1584                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1585                 if (FAILED(psresult))
1586                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1587         }
1588         // free the shader data
1589         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1590         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1591 }
1592
1593 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1594 {
1595         int i;
1596         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1597         int vertstring_length = 0;
1598         int geomstring_length = 0;
1599         int fragstring_length = 0;
1600         char *t;
1601         char *vertexstring, *geometrystring, *fragmentstring;
1602         char *vertstring, *geomstring, *fragstring;
1603         char permutationname[256];
1604         char cachename[256];
1605         int vertstrings_count = 0;
1606         int geomstrings_count = 0;
1607         int fragstrings_count = 0;
1608         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1609         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1610         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1611
1612         if (p->compiled)
1613                 return;
1614         p->compiled = true;
1615         p->vertexshader = NULL;
1616         p->pixelshader = NULL;
1617
1618         permutationname[0] = 0;
1619         cachename[0] = 0;
1620         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1621         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1622         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1623
1624         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1625         strlcat(cachename, "hlsl/", sizeof(cachename));
1626
1627         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1628         vertstrings_count = 0;
1629         geomstrings_count = 0;
1630         fragstrings_count = 0;
1631         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1632         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1633         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1634
1635         // the first pretext is which type of shader to compile as
1636         // (later these will all be bound together as a program object)
1637         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1638         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1639         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1640
1641         // the second pretext is the mode (for example a light source)
1642         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1643         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1644         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1645         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1646         strlcat(cachename, modeinfo->name, sizeof(cachename));
1647
1648         // now add all the permutation pretexts
1649         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1650         {
1651                 if (permutation & (1<<i))
1652                 {
1653                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1654                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1655                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1656                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1657                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1658                 }
1659                 else
1660                 {
1661                         // keep line numbers correct
1662                         vertstrings_list[vertstrings_count++] = "\n";
1663                         geomstrings_list[geomstrings_count++] = "\n";
1664                         fragstrings_list[fragstrings_count++] = "\n";
1665                 }
1666         }
1667
1668         // add static parms
1669         R_CompileShader_AddStaticParms(mode, permutation);
1670         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1671         vertstrings_count += shaderstaticparms_count;
1672         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1673         geomstrings_count += shaderstaticparms_count;
1674         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1675         fragstrings_count += shaderstaticparms_count;
1676
1677         // replace spaces in the cachename with _ characters
1678         for (i = 0;cachename[i];i++)
1679                 if (cachename[i] == ' ')
1680                         cachename[i] = '_';
1681
1682         // now append the shader text itself
1683         vertstrings_list[vertstrings_count++] = vertexstring;
1684         geomstrings_list[geomstrings_count++] = geometrystring;
1685         fragstrings_list[fragstrings_count++] = fragmentstring;
1686
1687         // if any sources were NULL, clear the respective list
1688         if (!vertexstring)
1689                 vertstrings_count = 0;
1690         if (!geometrystring)
1691                 geomstrings_count = 0;
1692         if (!fragmentstring)
1693                 fragstrings_count = 0;
1694
1695         vertstring_length = 0;
1696         for (i = 0;i < vertstrings_count;i++)
1697                 vertstring_length += strlen(vertstrings_list[i]);
1698         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1699         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1700                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1701
1702         geomstring_length = 0;
1703         for (i = 0;i < geomstrings_count;i++)
1704                 geomstring_length += strlen(geomstrings_list[i]);
1705         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1706         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1707                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1708
1709         fragstring_length = 0;
1710         for (i = 0;i < fragstrings_count;i++)
1711                 fragstring_length += strlen(fragstrings_list[i]);
1712         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1713         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1714                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1715
1716         // try to load the cached shader, or generate one
1717         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1718
1719         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1720                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1721         else
1722                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1723
1724         // free the strings
1725         if (vertstring)
1726                 Mem_Free(vertstring);
1727         if (geomstring)
1728                 Mem_Free(geomstring);
1729         if (fragstring)
1730                 Mem_Free(fragstring);
1731         if (vertexstring)
1732                 Mem_Free(vertexstring);
1733         if (geometrystring)
1734                 Mem_Free(geometrystring);
1735         if (fragmentstring)
1736                 Mem_Free(fragmentstring);
1737 }
1738
1739 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1740 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1741 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);}
1742 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);}
1743 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);}
1744 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);}
1745
1746 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1747 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1748 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);}
1749 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);}
1750 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);}
1751 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);}
1752
1753 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1754 {
1755         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1756         if (r_hlsl_permutation != perm)
1757         {
1758                 r_hlsl_permutation = perm;
1759                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1760                 {
1761                         if (!r_hlsl_permutation->compiled)
1762                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1763                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1764                         {
1765                                 // remove features until we find a valid permutation
1766                                 int i;
1767                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1768                                 {
1769                                         // reduce i more quickly whenever it would not remove any bits
1770                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1771                                         if (!(permutation & j))
1772                                                 continue;
1773                                         permutation -= j;
1774                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1775                                         if (!r_hlsl_permutation->compiled)
1776                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1777                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1778                                                 break;
1779                                 }
1780                                 if (i >= SHADERPERMUTATION_COUNT)
1781                                 {
1782                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1783                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1784                                         return; // no bit left to clear, entire mode is broken
1785                                 }
1786                         }
1787                 }
1788                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1789                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1790         }
1791         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1792         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1793         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1794 }
1795 #endif
1796
1797 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1798 {
1799         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1800         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1801         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1802         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1803 }
1804
1805 void R_GLSL_Restart_f(void)
1806 {
1807         unsigned int i, limit;
1808         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1809                 Mem_Free(glslshaderstring);
1810         glslshaderstring = NULL;
1811         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1812                 Mem_Free(hlslshaderstring);
1813         hlslshaderstring = NULL;
1814         switch(vid.renderpath)
1815         {
1816         case RENDERPATH_D3D9:
1817 #ifdef SUPPORTD3D
1818                 {
1819                         r_hlsl_permutation_t *p;
1820                         r_hlsl_permutation = NULL;
1821                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1822                         for (i = 0;i < limit;i++)
1823                         {
1824                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1825                                 {
1826                                         if (p->vertexshader)
1827                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1828                                         if (p->pixelshader)
1829                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1830                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1831                                 }
1832                         }
1833                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1834                 }
1835 #endif
1836                 break;
1837         case RENDERPATH_D3D10:
1838                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1839                 break;
1840         case RENDERPATH_D3D11:
1841                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1842                 break;
1843         case RENDERPATH_GL20:
1844         case RENDERPATH_GLES2:
1845                 {
1846                         r_glsl_permutation_t *p;
1847                         r_glsl_permutation = NULL;
1848                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1849                         for (i = 0;i < limit;i++)
1850                         {
1851                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1852                                 {
1853                                         GL_Backend_FreeProgram(p->program);
1854                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1855                                 }
1856                         }
1857                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1858                 }
1859                 break;
1860         case RENDERPATH_GL11:
1861         case RENDERPATH_GL13:
1862         case RENDERPATH_GLES1:
1863                 break;
1864         case RENDERPATH_SOFT:
1865                 break;
1866         }
1867 }
1868
1869 void R_GLSL_DumpShader_f(void)
1870 {
1871         int i;
1872         qfile_t *file;
1873
1874         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1875         if (file)
1876         {
1877                 FS_Print(file, "/* The engine may define the following macros:\n");
1878                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1879                 for (i = 0;i < SHADERMODE_COUNT;i++)
1880                         FS_Print(file, glslshadermodeinfo[i].pretext);
1881                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1882                         FS_Print(file, shaderpermutationinfo[i].pretext);
1883                 FS_Print(file, "*/\n");
1884                 FS_Print(file, builtinshaderstring);
1885                 FS_Close(file);
1886                 Con_Printf("glsl/default.glsl written\n");
1887         }
1888         else
1889                 Con_Printf("failed to write to glsl/default.glsl\n");
1890
1891         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1892         if (file)
1893         {
1894                 FS_Print(file, "/* The engine may define the following macros:\n");
1895                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1896                 for (i = 0;i < SHADERMODE_COUNT;i++)
1897                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1898                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1899                         FS_Print(file, shaderpermutationinfo[i].pretext);
1900                 FS_Print(file, "*/\n");
1901                 FS_Print(file, builtinhlslshaderstring);
1902                 FS_Close(file);
1903                 Con_Printf("hlsl/default.hlsl written\n");
1904         }
1905         else
1906                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1907 }
1908
1909 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1910 {
1911         if (!second)
1912                 texturemode = GL_MODULATE;
1913         switch (vid.renderpath)
1914         {
1915         case RENDERPATH_D3D9:
1916 #ifdef SUPPORTD3D
1917                 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))));
1918                 R_Mesh_TexBind(GL20TU_FIRST , first );
1919                 R_Mesh_TexBind(GL20TU_SECOND, second);
1920 #endif
1921                 break;
1922         case RENDERPATH_D3D10:
1923                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1924                 break;
1925         case RENDERPATH_D3D11:
1926                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1927                 break;
1928         case RENDERPATH_GL20:
1929         case RENDERPATH_GLES2:
1930                 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))));
1931                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1932                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1933                 break;
1934         case RENDERPATH_GL13:
1935         case RENDERPATH_GLES1:
1936                 R_Mesh_TexBind(0, first );
1937                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1938                 R_Mesh_TexBind(1, second);
1939                 if (second)
1940                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1941                 break;
1942         case RENDERPATH_GL11:
1943                 R_Mesh_TexBind(0, first );
1944                 break;
1945         case RENDERPATH_SOFT:
1946                 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))));
1947                 R_Mesh_TexBind(GL20TU_FIRST , first );
1948                 R_Mesh_TexBind(GL20TU_SECOND, second);
1949                 break;
1950         }
1951 }
1952
1953 void R_SetupShader_DepthOrShadow(void)
1954 {
1955         switch (vid.renderpath)
1956         {
1957         case RENDERPATH_D3D9:
1958 #ifdef SUPPORTD3D
1959                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1960 #endif
1961                 break;
1962         case RENDERPATH_D3D10:
1963                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1964                 break;
1965         case RENDERPATH_D3D11:
1966                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1967                 break;
1968         case RENDERPATH_GL20:
1969         case RENDERPATH_GLES2:
1970                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1971                 break;
1972         case RENDERPATH_GL13:
1973         case RENDERPATH_GLES1:
1974                 R_Mesh_TexBind(0, 0);
1975                 R_Mesh_TexBind(1, 0);
1976                 break;
1977         case RENDERPATH_GL11:
1978                 R_Mesh_TexBind(0, 0);
1979                 break;
1980         case RENDERPATH_SOFT:
1981                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1982                 break;
1983         }
1984 }
1985
1986 void R_SetupShader_ShowDepth(void)
1987 {
1988         switch (vid.renderpath)
1989         {
1990         case RENDERPATH_D3D9:
1991 #ifdef SUPPORTHLSL
1992                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1993 #endif
1994                 break;
1995         case RENDERPATH_D3D10:
1996                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1997                 break;
1998         case RENDERPATH_D3D11:
1999                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2000                 break;
2001         case RENDERPATH_GL20:
2002         case RENDERPATH_GLES2:
2003                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
2004                 break;
2005         case RENDERPATH_GL13:
2006         case RENDERPATH_GLES1:
2007                 break;
2008         case RENDERPATH_GL11:
2009                 break;
2010         case RENDERPATH_SOFT:
2011                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2012                 break;
2013         }
2014 }
2015
2016 extern qboolean r_shadow_usingdeferredprepass;
2017 extern cvar_t r_shadow_deferred_8bitrange;
2018 extern rtexture_t *r_shadow_attenuationgradienttexture;
2019 extern rtexture_t *r_shadow_attenuation2dtexture;
2020 extern rtexture_t *r_shadow_attenuation3dtexture;
2021 extern qboolean r_shadow_usingshadowmap2d;
2022 extern qboolean r_shadow_usingshadowmaportho;
2023 extern float r_shadow_shadowmap_texturescale[2];
2024 extern float r_shadow_shadowmap_parameters[4];
2025 extern qboolean r_shadow_shadowmapvsdct;
2026 extern qboolean r_shadow_shadowmapsampler;
2027 extern int r_shadow_shadowmappcf;
2028 extern rtexture_t *r_shadow_shadowmap2dtexture;
2029 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2030 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2031 extern matrix4x4_t r_shadow_shadowmapmatrix;
2032 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2033 extern int r_shadow_prepass_width;
2034 extern int r_shadow_prepass_height;
2035 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2036 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2037 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2038 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2039 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2040
2041 #define BLENDFUNC_ALLOWS_COLORMOD      1
2042 #define BLENDFUNC_ALLOWS_FOG           2
2043 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2044 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2045 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2046 static int R_BlendFuncFlags(int src, int dst)
2047 {
2048         int r = 0;
2049
2050         // a blendfunc allows colormod if:
2051         // a) it can never keep the destination pixel invariant, or
2052         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2053         // this is to prevent unintended side effects from colormod
2054
2055         // a blendfunc allows fog if:
2056         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2057         // this is to prevent unintended side effects from fog
2058
2059         // these checks are the output of fogeval.pl
2060
2061         r |= BLENDFUNC_ALLOWS_COLORMOD;
2062         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2063         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2064         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2065         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2066         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2067         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2068         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2069         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2070         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2071         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2072         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2073         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2074         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2075         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2076         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2077         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2078         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2079         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2080         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2081         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2082         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2083
2084         return r;
2085 }
2086
2087 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)
2088 {
2089         // select a permutation of the lighting shader appropriate to this
2090         // combination of texture, entity, light source, and fogging, only use the
2091         // minimum features necessary to avoid wasting rendering time in the
2092         // fragment shader on features that are not being used
2093         unsigned int permutation = 0;
2094         unsigned int mode = 0;
2095         int blendfuncflags;
2096         static float dummy_colormod[3] = {1, 1, 1};
2097         float *colormod = rsurface.colormod;
2098         float m16f[16];
2099         matrix4x4_t tempmatrix;
2100         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2101         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2102                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2103         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2104                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2105         if (rsurfacepass == RSURFPASS_BACKGROUND)
2106         {
2107                 // distorted background
2108                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2109                 {
2110                         mode = SHADERMODE_WATER;
2111                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2112                         {
2113                                 // this is the right thing to do for wateralpha
2114                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2115                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2116                         }
2117                         else
2118                         {
2119                                 // this is the right thing to do for entity alpha
2120                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2121                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2122                         }
2123                 }
2124                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2125                 {
2126                         mode = SHADERMODE_REFRACTION;
2127                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2128                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2129                 }
2130                 else
2131                 {
2132                         mode = SHADERMODE_GENERIC;
2133                         permutation |= SHADERPERMUTATION_DIFFUSE;
2134                         GL_BlendFunc(GL_ONE, GL_ZERO);
2135                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2136                 }
2137         }
2138         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2139         {
2140                 if (r_glsl_offsetmapping.integer)
2141                 {
2142                         switch(rsurface.texture->offsetmapping)
2143                         {
2144                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2145                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2146                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2147                         case OFFSETMAPPING_OFF: break;
2148                         }
2149                 }
2150                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2151                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2152                 // normalmap (deferred prepass), may use alpha test on diffuse
2153                 mode = SHADERMODE_DEFERREDGEOMETRY;
2154                 GL_BlendFunc(GL_ONE, GL_ZERO);
2155                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2156         }
2157         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2158         {
2159                 if (r_glsl_offsetmapping.integer)
2160                 {
2161                         switch(rsurface.texture->offsetmapping)
2162                         {
2163                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2164                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2165                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2166                         case OFFSETMAPPING_OFF: break;
2167                         }
2168                 }
2169                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2170                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2171                 // light source
2172                 mode = SHADERMODE_LIGHTSOURCE;
2173                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2174                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2175                 if (diffusescale > 0)
2176                         permutation |= SHADERPERMUTATION_DIFFUSE;
2177                 if (specularscale > 0)
2178                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2179                 if (r_refdef.fogenabled)
2180                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2181                 if (rsurface.texture->colormapping)
2182                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2183                 if (r_shadow_usingshadowmap2d)
2184                 {
2185                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2186                         if(r_shadow_shadowmapvsdct)
2187                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2188
2189                         if (r_shadow_shadowmapsampler)
2190                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2191                         if (r_shadow_shadowmappcf > 1)
2192                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2193                         else if (r_shadow_shadowmappcf)
2194                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2195                 }
2196                 if (rsurface.texture->reflectmasktexture)
2197                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2198                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2199                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2200         }
2201         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2202         {
2203                 if (r_glsl_offsetmapping.integer)
2204                 {
2205                         switch(rsurface.texture->offsetmapping)
2206                         {
2207                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2208                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2209                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2210                         case OFFSETMAPPING_OFF: break;
2211                         }
2212                 }
2213                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2214                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2215                 // unshaded geometry (fullbright or ambient model lighting)
2216                 mode = SHADERMODE_FLATCOLOR;
2217                 ambientscale = diffusescale = specularscale = 0;
2218                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2219                         permutation |= SHADERPERMUTATION_GLOW;
2220                 if (r_refdef.fogenabled)
2221                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2222                 if (rsurface.texture->colormapping)
2223                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2224                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2225                 {
2226                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2227                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2228
2229                         if (r_shadow_shadowmapsampler)
2230                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2231                         if (r_shadow_shadowmappcf > 1)
2232                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2233                         else if (r_shadow_shadowmappcf)
2234                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2235                 }
2236                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2237                         permutation |= SHADERPERMUTATION_REFLECTION;
2238                 if (rsurface.texture->reflectmasktexture)
2239                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2240                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2241                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2242         }
2243         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2244         {
2245                 if (r_glsl_offsetmapping.integer)
2246                 {
2247                         switch(rsurface.texture->offsetmapping)
2248                         {
2249                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2250                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2251                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2252                         case OFFSETMAPPING_OFF: break;
2253                         }
2254                 }
2255                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2256                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2257                 // directional model lighting
2258                 mode = SHADERMODE_LIGHTDIRECTION;
2259                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2260                         permutation |= SHADERPERMUTATION_GLOW;
2261                 permutation |= SHADERPERMUTATION_DIFFUSE;
2262                 if (specularscale > 0)
2263                         permutation |= SHADERPERMUTATION_SPECULAR;
2264                 if (r_refdef.fogenabled)
2265                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2266                 if (rsurface.texture->colormapping)
2267                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2268                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2269                 {
2270                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2271                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2272
2273                         if (r_shadow_shadowmapsampler)
2274                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2275                         if (r_shadow_shadowmappcf > 1)
2276                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2277                         else if (r_shadow_shadowmappcf)
2278                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2279                 }
2280                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2281                         permutation |= SHADERPERMUTATION_REFLECTION;
2282                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2283                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2284                 if (rsurface.texture->reflectmasktexture)
2285                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2286                 if (r_shadow_bouncegridtexture)
2287                 {
2288                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2289                         if (r_shadow_bouncegriddirectional)
2290                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2291                 }
2292                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2293                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2294         }
2295         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2296         {
2297                 if (r_glsl_offsetmapping.integer)
2298                 {
2299                         switch(rsurface.texture->offsetmapping)
2300                         {
2301                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2302                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2303                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2304                         case OFFSETMAPPING_OFF: break;
2305                         }
2306                 }
2307                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2308                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2309                 // ambient model lighting
2310                 mode = SHADERMODE_LIGHTDIRECTION;
2311                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2312                         permutation |= SHADERPERMUTATION_GLOW;
2313                 if (r_refdef.fogenabled)
2314                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2315                 if (rsurface.texture->colormapping)
2316                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2317                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2318                 {
2319                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2320                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2321
2322                         if (r_shadow_shadowmapsampler)
2323                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2324                         if (r_shadow_shadowmappcf > 1)
2325                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2326                         else if (r_shadow_shadowmappcf)
2327                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2328                 }
2329                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2330                         permutation |= SHADERPERMUTATION_REFLECTION;
2331                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2332                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2333                 if (rsurface.texture->reflectmasktexture)
2334                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2335                 if (r_shadow_bouncegridtexture)
2336                 {
2337                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2338                         if (r_shadow_bouncegriddirectional)
2339                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2340                 }
2341                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2342                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2343         }
2344         else
2345         {
2346                 if (r_glsl_offsetmapping.integer)
2347                 {
2348                         switch(rsurface.texture->offsetmapping)
2349                         {
2350                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2351                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2352                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2353                         case OFFSETMAPPING_OFF: break;
2354                         }
2355                 }
2356                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2357                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2358                 // lightmapped wall
2359                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2360                         permutation |= SHADERPERMUTATION_GLOW;
2361                 if (r_refdef.fogenabled)
2362                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2363                 if (rsurface.texture->colormapping)
2364                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2365                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2366                 {
2367                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2368                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2369
2370                         if (r_shadow_shadowmapsampler)
2371                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2372                         if (r_shadow_shadowmappcf > 1)
2373                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2374                         else if (r_shadow_shadowmappcf)
2375                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2376                 }
2377                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2378                         permutation |= SHADERPERMUTATION_REFLECTION;
2379                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2380                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2381                 if (rsurface.texture->reflectmasktexture)
2382                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2383                 if (FAKELIGHT_ENABLED)
2384                 {
2385                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2386                         mode = SHADERMODE_FAKELIGHT;
2387                         permutation |= SHADERPERMUTATION_DIFFUSE;
2388                         if (specularscale > 0)
2389                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2390                 }
2391                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2392                 {
2393                         // deluxemapping (light direction texture)
2394                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2395                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2396                         else
2397                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2398                         permutation |= SHADERPERMUTATION_DIFFUSE;
2399                         if (specularscale > 0)
2400                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2401                 }
2402                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2403                 {
2404                         // fake deluxemapping (uniform light direction in tangentspace)
2405                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2406                         permutation |= SHADERPERMUTATION_DIFFUSE;
2407                         if (specularscale > 0)
2408                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2409                 }
2410                 else if (rsurface.uselightmaptexture)
2411                 {
2412                         // ordinary lightmapping (q1bsp, q3bsp)
2413                         mode = SHADERMODE_LIGHTMAP;
2414                 }
2415                 else
2416                 {
2417                         // ordinary vertex coloring (q3bsp)
2418                         mode = SHADERMODE_VERTEXCOLOR;
2419                 }
2420                 if (r_shadow_bouncegridtexture)
2421                 {
2422                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2423                         if (r_shadow_bouncegriddirectional)
2424                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2425                 }
2426                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2427                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2428         }
2429         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2430                 colormod = dummy_colormod;
2431         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2432                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2433         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2434                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2435         switch(vid.renderpath)
2436         {
2437         case RENDERPATH_D3D9:
2438 #ifdef SUPPORTD3D
2439                 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);
2440                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2441                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2442                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2443                 if (mode == SHADERMODE_LIGHTSOURCE)
2444                 {
2445                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2446                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2447                 }
2448                 else
2449                 {
2450                         if (mode == SHADERMODE_LIGHTDIRECTION)
2451                         {
2452                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2453                         }
2454                 }
2455                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2456                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2457                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2458                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2459                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2460
2461                 if (mode == SHADERMODE_LIGHTSOURCE)
2462                 {
2463                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2464                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2465                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2466                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2467                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2468
2469                         // additive passes are only darkened by fog, not tinted
2470                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2471                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2472                 }
2473                 else
2474                 {
2475                         if (mode == SHADERMODE_FLATCOLOR)
2476                         {
2477                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2478                         }
2479                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2480                         {
2481                                 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]);
2482                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2483                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2484                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2485                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2486                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2487                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2488                         }
2489                         else
2490                         {
2491                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2492                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2493                                 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);
2494                                 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);
2495                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2496                         }
2497                         // additive passes are only darkened by fog, not tinted
2498                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2499                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2500                         else
2501                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2502                         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);
2503                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2504                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2505                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2506                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2507                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2508                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2509                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2510                         if (mode == SHADERMODE_WATER)
2511                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2512                 }
2513                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2514                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2515                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2516                 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));
2517                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2518                 if (rsurface.texture->pantstexture)
2519                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2520                 else
2521                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2522                 if (rsurface.texture->shirttexture)
2523                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2524                 else
2525                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2526                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2527                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2528                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2529                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2530                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2531                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2532                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2533                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2534                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2535                         );
2536                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2537                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2538
2539                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2540                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2541                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2542                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2543                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2544                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2545                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2546                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2547                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2548                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2549                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2550                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2551                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2552                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2553                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2554                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2555                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2556                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2557                 {
2558                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2559                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2560                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2561                 }
2562                 else
2563                 {
2564                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2565                 }
2566 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2567 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2568                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2569                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2570                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2571                 {
2572                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2573                         if (rsurface.rtlight)
2574                         {
2575                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2576                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2577                         }
2578                 }
2579 #endif
2580                 break;
2581         case RENDERPATH_D3D10:
2582                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2583                 break;
2584         case RENDERPATH_D3D11:
2585                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2586                 break;
2587         case RENDERPATH_GL20:
2588         case RENDERPATH_GLES2:
2589                 if (!vid.useinterleavedarrays)
2590                 {
2591                         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);
2592                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2593                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2594                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2595                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2596                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2597                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2598                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2599                 }
2600                 else
2601                 {
2602                         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);
2603                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2604                 }
2605                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2606                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2607                 if (mode == SHADERMODE_LIGHTSOURCE)
2608                 {
2609                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2610                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2611                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2612                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2613                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2614                         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);
2615         
2616                         // additive passes are only darkened by fog, not tinted
2617                         if (r_glsl_permutation->loc_FogColor >= 0)
2618                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2619                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2620                 }
2621                 else
2622                 {
2623                         if (mode == SHADERMODE_FLATCOLOR)
2624                         {
2625                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2626                         }
2627                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2628                         {
2629                                 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]);
2630                                 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]);
2631                                 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);
2632                                 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);
2633                                 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);
2634                                 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]);
2635                                 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]);
2636                         }
2637                         else
2638                         {
2639                                 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]);
2640                                 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]);
2641                                 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);
2642                                 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);
2643                                 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);
2644                         }
2645                         // additive passes are only darkened by fog, not tinted
2646                         if (r_glsl_permutation->loc_FogColor >= 0)
2647                         {
2648                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2649                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2650                                 else
2651                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2652                         }
2653                         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);
2654                         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]);
2655                         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]);
2656                         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]);
2657                         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]);
2658                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2659                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2660                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2661                         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]);
2662                 }
2663                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2664                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2665                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2666                 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]);
2667                 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]);
2668
2669                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2670                 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));
2671                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2672                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2673                 {
2674                         if (rsurface.texture->pantstexture)
2675                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2676                         else
2677                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2678                 }
2679                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2680                 {
2681                         if (rsurface.texture->shirttexture)
2682                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2683                         else
2684                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2685                 }
2686                 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]);
2687                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2688                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2689                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2690                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2691                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2692                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2693                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2694                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2695                         );
2696                 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]);
2697                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2698                 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);}
2699                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2700
2701                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2702                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2703                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2704                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2705                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2706                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2707                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2708                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2709                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2710                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2711                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2712                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2713                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2714                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2715                 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);
2716                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2717                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2718                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2719                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2720                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2721                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2722                 {
2723                         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);
2724                         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);
2725                         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);
2726                 }
2727                 else
2728                 {
2729                         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);
2730                 }
2731                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2732                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2733                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2734                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2735                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2736                 {
2737                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2738                         if (rsurface.rtlight)
2739                         {
2740                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2741                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2742                         }
2743                 }
2744                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2745                 CHECKGLERROR
2746                 break;
2747         case RENDERPATH_GL11:
2748         case RENDERPATH_GL13:
2749         case RENDERPATH_GLES1:
2750                 break;
2751         case RENDERPATH_SOFT:
2752                 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);
2753                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2754                 R_SetupShader_SetPermutationSoft(mode, permutation);
2755                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2756                 if (mode == SHADERMODE_LIGHTSOURCE)
2757                 {
2758                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2759                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2760                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2761                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2762                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2763                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2764         
2765                         // additive passes are only darkened by fog, not tinted
2766                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2767                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2768                 }
2769                 else
2770                 {
2771                         if (mode == SHADERMODE_FLATCOLOR)
2772                         {
2773                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2774                         }
2775                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2776                         {
2777                                 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]);
2778                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2779                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2780                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2781                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2782                                 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]);
2783                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2784                         }
2785                         else
2786                         {
2787                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2788                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2789                                 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);
2790                                 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);
2791                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2792                         }
2793                         // additive passes are only darkened by fog, not tinted
2794                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2795                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2796                         else
2797                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2798                         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);
2799                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2800                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2801                         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]);
2802                         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]);
2803                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2804                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2805                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2806                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2807                 }
2808                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2809                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2810                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2811                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2812                 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]);
2813
2814                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2815                 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));
2816                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2817                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2818                 {
2819                         if (rsurface.texture->pantstexture)
2820                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2821                         else
2822                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2823                 }
2824                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2825                 {
2826                         if (rsurface.texture->shirttexture)
2827                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2828                         else
2829                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2830                 }
2831                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2832                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2833                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2834                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2835                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2836                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2837                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2838                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2839                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2840                         );
2841                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2842                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2843
2844                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2845                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2846                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2847                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2848                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2849                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2850                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2851                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2852                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2853                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2854                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2855                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2856                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2857                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2858                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2859                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2860                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2861                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2862                 {
2863                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2864                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2865                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2866                 }
2867                 else
2868                 {
2869                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2870                 }
2871 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2872 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2873                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2874                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2875                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2876                 {
2877                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2878                         if (rsurface.rtlight)
2879                         {
2880                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2881                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2882                         }
2883                 }
2884                 break;
2885         }
2886 }
2887
2888 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2889 {
2890         // select a permutation of the lighting shader appropriate to this
2891         // combination of texture, entity, light source, and fogging, only use the
2892         // minimum features necessary to avoid wasting rendering time in the
2893         // fragment shader on features that are not being used
2894         unsigned int permutation = 0;
2895         unsigned int mode = 0;
2896         const float *lightcolorbase = rtlight->currentcolor;
2897         float ambientscale = rtlight->ambientscale;
2898         float diffusescale = rtlight->diffusescale;
2899         float specularscale = rtlight->specularscale;
2900         // this is the location of the light in view space
2901         vec3_t viewlightorigin;
2902         // this transforms from view space (camera) to light space (cubemap)
2903         matrix4x4_t viewtolight;
2904         matrix4x4_t lighttoview;
2905         float viewtolight16f[16];
2906         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2907         // light source
2908         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2909         if (rtlight->currentcubemap != r_texture_whitecube)
2910                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2911         if (diffusescale > 0)
2912                 permutation |= SHADERPERMUTATION_DIFFUSE;
2913         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2914                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2915         if (r_shadow_usingshadowmap2d)
2916         {
2917                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2918                 if (r_shadow_shadowmapvsdct)
2919                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2920
2921                 if (r_shadow_shadowmapsampler)
2922                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2923                 if (r_shadow_shadowmappcf > 1)
2924                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2925                 else if (r_shadow_shadowmappcf)
2926                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2927         }
2928         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2929         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2930         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2931         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2932         switch(vid.renderpath)
2933         {
2934         case RENDERPATH_D3D9:
2935 #ifdef SUPPORTD3D
2936                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2937                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2938                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2939                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2940                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2941                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2942                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2943                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2944                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2945                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2946                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2947
2948                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2949                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2950                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2951                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2952                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2953                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2954 #endif
2955                 break;
2956         case RENDERPATH_D3D10:
2957                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2958                 break;
2959         case RENDERPATH_D3D11:
2960                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2961                 break;
2962         case RENDERPATH_GL20:
2963         case RENDERPATH_GLES2:
2964                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2965                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2966                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2967                 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);
2968                 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);
2969                 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);
2970                 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]);
2971                 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]);
2972                 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));
2973                 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]);
2974                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2975
2976                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2977                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2978                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2979                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2980                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2981                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2982                 break;
2983         case RENDERPATH_GL11:
2984         case RENDERPATH_GL13:
2985         case RENDERPATH_GLES1:
2986                 break;
2987         case RENDERPATH_SOFT:
2988                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2989                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2990                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2991                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2992                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2993                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2994                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2995                 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]);
2996                 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));
2997                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2998                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2999
3000                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3001                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3002                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3003                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3004                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3005                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3006                 break;
3007         }
3008 }
3009
3010 #define SKINFRAME_HASH 1024
3011
3012 typedef struct
3013 {
3014         int loadsequence; // incremented each level change
3015         memexpandablearray_t array;
3016         skinframe_t *hash[SKINFRAME_HASH];
3017 }
3018 r_skinframe_t;
3019 r_skinframe_t r_skinframe;
3020
3021 void R_SkinFrame_PrepareForPurge(void)
3022 {
3023         r_skinframe.loadsequence++;
3024         // wrap it without hitting zero
3025         if (r_skinframe.loadsequence >= 200)
3026                 r_skinframe.loadsequence = 1;
3027 }
3028
3029 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3030 {
3031         if (!skinframe)
3032                 return;
3033         // mark the skinframe as used for the purging code
3034         skinframe->loadsequence = r_skinframe.loadsequence;
3035 }
3036
3037 void R_SkinFrame_Purge(void)
3038 {
3039         int i;
3040         skinframe_t *s;
3041         for (i = 0;i < SKINFRAME_HASH;i++)
3042         {
3043                 for (s = r_skinframe.hash[i];s;s = s->next)
3044                 {
3045                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3046                         {
3047                                 if (s->merged == s->base)
3048                                         s->merged = NULL;
3049                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3050                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3051                                 R_PurgeTexture(s->merged);s->merged = NULL;
3052                                 R_PurgeTexture(s->base  );s->base   = NULL;
3053                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3054                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3055                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3056                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3057                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3058                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3059                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3060                                 s->loadsequence = 0;
3061                         }
3062                 }
3063         }
3064 }
3065
3066 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3067         skinframe_t *item;
3068         char basename[MAX_QPATH];
3069
3070         Image_StripImageExtension(name, basename, sizeof(basename));
3071
3072         if( last == NULL ) {
3073                 int hashindex;
3074                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3075                 item = r_skinframe.hash[hashindex];
3076         } else {
3077                 item = last->next;
3078         }
3079
3080         // linearly search through the hash bucket
3081         for( ; item ; item = item->next ) {
3082                 if( !strcmp( item->basename, basename ) ) {
3083                         return item;
3084                 }
3085         }
3086         return NULL;
3087 }
3088
3089 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3090 {
3091         skinframe_t *item;
3092         int hashindex;
3093         char basename[MAX_QPATH];
3094
3095         Image_StripImageExtension(name, basename, sizeof(basename));
3096
3097         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3098         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3099                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3100                         break;
3101
3102         if (!item) {
3103                 rtexture_t *dyntexture;
3104                 // check whether its a dynamic texture
3105                 dyntexture = CL_GetDynTexture( basename );
3106                 if (!add && !dyntexture)
3107                         return NULL;
3108                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3109                 memset(item, 0, sizeof(*item));
3110                 strlcpy(item->basename, basename, sizeof(item->basename));
3111                 item->base = dyntexture; // either NULL or dyntexture handle
3112                 item->textureflags = textureflags;
3113                 item->comparewidth = comparewidth;
3114                 item->compareheight = compareheight;
3115                 item->comparecrc = comparecrc;
3116                 item->next = r_skinframe.hash[hashindex];
3117                 r_skinframe.hash[hashindex] = item;
3118         }
3119         else if( item->base == NULL )
3120         {
3121                 rtexture_t *dyntexture;
3122                 // check whether its a dynamic texture
3123                 // 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]
3124                 dyntexture = CL_GetDynTexture( basename );
3125                 item->base = dyntexture; // either NULL or dyntexture handle
3126         }
3127
3128         R_SkinFrame_MarkUsed(item);
3129         return item;
3130 }
3131
3132 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3133         { \
3134                 unsigned long long avgcolor[5], wsum; \
3135                 int pix, comp, w; \
3136                 avgcolor[0] = 0; \
3137                 avgcolor[1] = 0; \
3138                 avgcolor[2] = 0; \
3139                 avgcolor[3] = 0; \
3140                 avgcolor[4] = 0; \
3141                 wsum = 0; \
3142                 for(pix = 0; pix < cnt; ++pix) \
3143                 { \
3144                         w = 0; \
3145                         for(comp = 0; comp < 3; ++comp) \
3146                                 w += getpixel; \
3147                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3148                         { \
3149                                 ++wsum; \
3150                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3151                                 w = getpixel; \
3152                                 for(comp = 0; comp < 3; ++comp) \
3153                                         avgcolor[comp] += getpixel * w; \
3154                                 avgcolor[3] += w; \
3155                         } \
3156                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3157                         avgcolor[4] += getpixel; \
3158                 } \
3159                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3160                         avgcolor[3] = 1; \
3161                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3162                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3163                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3164                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3165         }
3166
3167 extern cvar_t gl_picmip;
3168 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3169 {
3170         int j;
3171         unsigned char *pixels;
3172         unsigned char *bumppixels;
3173         unsigned char *basepixels = NULL;
3174         int basepixels_width = 0;
3175         int basepixels_height = 0;
3176         skinframe_t *skinframe;
3177         rtexture_t *ddsbase = NULL;
3178         qboolean ddshasalpha = false;
3179         float ddsavgcolor[4];
3180         char basename[MAX_QPATH];
3181         int miplevel = R_PicmipForFlags(textureflags);
3182         int savemiplevel = miplevel;
3183         int mymiplevel;
3184
3185         if (cls.state == ca_dedicated)
3186                 return NULL;
3187
3188         // return an existing skinframe if already loaded
3189         // if loading of the first image fails, don't make a new skinframe as it
3190         // would cause all future lookups of this to be missing
3191         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3192         if (skinframe && skinframe->base)
3193                 return skinframe;
3194
3195         Image_StripImageExtension(name, basename, sizeof(basename));
3196
3197         // check for DDS texture file first
3198         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3199         {
3200                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3201                 if (basepixels == NULL)
3202                         return NULL;
3203         }
3204
3205         // FIXME handle miplevel
3206
3207         if (developer_loading.integer)
3208                 Con_Printf("loading skin \"%s\"\n", name);
3209
3210         // we've got some pixels to store, so really allocate this new texture now
3211         if (!skinframe)
3212                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3213         skinframe->stain = NULL;
3214         skinframe->merged = NULL;
3215         skinframe->base = NULL;
3216         skinframe->pants = NULL;
3217         skinframe->shirt = NULL;
3218         skinframe->nmap = NULL;
3219         skinframe->gloss = NULL;
3220         skinframe->glow = NULL;
3221         skinframe->fog = NULL;
3222         skinframe->reflect = NULL;
3223         skinframe->hasalpha = false;
3224
3225         if (ddsbase)
3226         {
3227                 skinframe->base = ddsbase;
3228                 skinframe->hasalpha = ddshasalpha;
3229                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3230                 if (r_loadfog && skinframe->hasalpha)
3231                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3232                 //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]);
3233         }
3234         else
3235         {
3236                 basepixels_width = image_width;
3237                 basepixels_height = image_height;
3238                 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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3239                 if (textureflags & TEXF_ALPHA)
3240                 {
3241                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3242                         {
3243                                 if (basepixels[j] < 255)
3244                                 {
3245                                         skinframe->hasalpha = true;
3246                                         break;
3247                                 }
3248                         }
3249                         if (r_loadfog && skinframe->hasalpha)
3250                         {
3251                                 // has transparent pixels
3252                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3253                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3254                                 {
3255                                         pixels[j+0] = 255;
3256                                         pixels[j+1] = 255;
3257                                         pixels[j+2] = 255;
3258                                         pixels[j+3] = basepixels[j+3];
3259                                 }
3260                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3261                                 Mem_Free(pixels);
3262                         }
3263                 }
3264                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3265                 //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]);
3266                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3267                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3268                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3269                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3270         }
3271
3272         if (r_loaddds)
3273         {
3274                 mymiplevel = savemiplevel;
3275                 if (r_loadnormalmap)
3276                         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);
3277                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3278                 if (r_loadgloss)
3279                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3280                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3281                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3282                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3283         }
3284
3285         // _norm is the name used by tenebrae and has been adopted as standard
3286         if (r_loadnormalmap && skinframe->nmap == NULL)
3287         {
3288                 mymiplevel = savemiplevel;
3289                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3290                 {
3291                         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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3292                         Mem_Free(pixels);
3293                         pixels = NULL;
3294                 }
3295                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3296                 {
3297                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3298                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3299                         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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3300                         Mem_Free(pixels);
3301                         Mem_Free(bumppixels);
3302                 }
3303                 else if (r_shadow_bumpscale_basetexture.value > 0)
3304                 {
3305                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3306                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3307                         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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3308                         Mem_Free(pixels);
3309                 }
3310                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3311                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3312         }
3313
3314         // _luma is supported only for tenebrae compatibility
3315         // _glow is the preferred name
3316         mymiplevel = savemiplevel;
3317         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))))
3318         {
3319                 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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3320                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3321                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3322                 Mem_Free(pixels);pixels = NULL;
3323         }
3324
3325         mymiplevel = savemiplevel;
3326         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3327         {
3328                 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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3329                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3330                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3331                 Mem_Free(pixels);
3332                 pixels = NULL;
3333         }
3334
3335         mymiplevel = savemiplevel;
3336         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3337         {
3338                 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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3339                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3340                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3341                 Mem_Free(pixels);
3342                 pixels = NULL;
3343         }
3344
3345         mymiplevel = savemiplevel;
3346         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3347         {
3348                 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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3349                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3350                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3351                 Mem_Free(pixels);
3352                 pixels = NULL;
3353         }
3354
3355         mymiplevel = savemiplevel;
3356         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3357         {
3358                 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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3359                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3360                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3361                 Mem_Free(pixels);
3362                 pixels = NULL;
3363         }
3364
3365         if (basepixels)
3366                 Mem_Free(basepixels);
3367
3368         return skinframe;
3369 }
3370
3371 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3372 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3373 {
3374         int i;
3375         unsigned char *temp1, *temp2;
3376         skinframe_t *skinframe;
3377
3378         if (cls.state == ca_dedicated)
3379                 return NULL;
3380
3381         // if already loaded just return it, otherwise make a new skinframe
3382         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3383         if (skinframe && skinframe->base)
3384                 return skinframe;
3385
3386         skinframe->stain = NULL;
3387         skinframe->merged = NULL;
3388         skinframe->base = NULL;
3389         skinframe->pants = NULL;
3390         skinframe->shirt = NULL;
3391         skinframe->nmap = NULL;
3392         skinframe->gloss = NULL;
3393         skinframe->glow = NULL;
3394         skinframe->fog = NULL;
3395         skinframe->reflect = NULL;
3396         skinframe->hasalpha = false;
3397
3398         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3399         if (!skindata)
3400                 return NULL;
3401
3402         if (developer_loading.integer)
3403                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3404
3405         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3406         {
3407                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3408                 temp2 = temp1 + width * height * 4;
3409                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3410                 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);
3411                 Mem_Free(temp1);
3412         }
3413         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3414         if (textureflags & TEXF_ALPHA)
3415         {
3416                 for (i = 3;i < width * height * 4;i += 4)
3417                 {
3418                         if (skindata[i] < 255)
3419                         {
3420                                 skinframe->hasalpha = true;
3421                                 break;
3422                         }
3423                 }
3424                 if (r_loadfog && skinframe->hasalpha)
3425                 {
3426                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3427                         memcpy(fogpixels, skindata, width * height * 4);
3428                         for (i = 0;i < width * height * 4;i += 4)
3429                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3430                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3431                         Mem_Free(fogpixels);
3432                 }
3433         }
3434
3435         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3436         //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]);
3437
3438         return skinframe;
3439 }
3440
3441 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3442 {
3443         int i;
3444         int featuresmask;
3445         skinframe_t *skinframe;
3446
3447         if (cls.state == ca_dedicated)
3448                 return NULL;
3449
3450         // if already loaded just return it, otherwise make a new skinframe
3451         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3452         if (skinframe && skinframe->base)
3453                 return skinframe;
3454
3455         skinframe->stain = NULL;
3456         skinframe->merged = NULL;
3457         skinframe->base = NULL;
3458         skinframe->pants = NULL;
3459         skinframe->shirt = NULL;
3460         skinframe->nmap = NULL;
3461         skinframe->gloss = NULL;
3462         skinframe->glow = NULL;
3463         skinframe->fog = NULL;
3464         skinframe->reflect = NULL;
3465         skinframe->hasalpha = false;
3466
3467         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3468         if (!skindata)
3469                 return NULL;
3470
3471         if (developer_loading.integer)
3472                 Con_Printf("loading quake skin \"%s\"\n", name);
3473
3474         // 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)
3475         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3476         memcpy(skinframe->qpixels, skindata, width*height);
3477         skinframe->qwidth = width;
3478         skinframe->qheight = height;
3479
3480         featuresmask = 0;
3481         for (i = 0;i < width * height;i++)
3482                 featuresmask |= palette_featureflags[skindata[i]];
3483
3484         skinframe->hasalpha = false;
3485         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3486         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3487         skinframe->qgeneratemerged = true;
3488         skinframe->qgeneratebase = skinframe->qhascolormapping;
3489         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3490
3491         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3492         //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]);
3493
3494         return skinframe;
3495 }
3496
3497 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3498 {
3499         int width;
3500         int height;
3501         unsigned char *skindata;
3502
3503         if (!skinframe->qpixels)
3504                 return;
3505
3506         if (!skinframe->qhascolormapping)
3507                 colormapped = false;
3508
3509         if (colormapped)
3510         {
3511                 if (!skinframe->qgeneratebase)
3512                         return;
3513         }
3514         else
3515         {
3516                 if (!skinframe->qgeneratemerged)
3517                         return;
3518         }
3519
3520         width = skinframe->qwidth;
3521         height = skinframe->qheight;
3522         skindata = skinframe->qpixels;
3523
3524         if (skinframe->qgeneratenmap)
3525         {
3526                 unsigned char *temp1, *temp2;
3527                 skinframe->qgeneratenmap = false;
3528                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3529                 temp2 = temp1 + width * height * 4;
3530                 // use either a custom palette or the quake palette
3531                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3532                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3533                 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);
3534                 Mem_Free(temp1);
3535         }
3536
3537         if (skinframe->qgenerateglow)
3538         {
3539                 skinframe->qgenerateglow = false;
3540                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3541         }
3542
3543         if (colormapped)
3544         {
3545                 skinframe->qgeneratebase = false;
3546                 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);
3547                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3548                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3549         }
3550         else
3551         {
3552                 skinframe->qgeneratemerged = false;
3553                 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);
3554         }
3555
3556         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3557         {
3558                 Mem_Free(skinframe->qpixels);
3559                 skinframe->qpixels = NULL;
3560         }
3561 }
3562
3563 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)
3564 {
3565         int i;
3566         skinframe_t *skinframe;
3567
3568         if (cls.state == ca_dedicated)
3569                 return NULL;
3570
3571         // if already loaded just return it, otherwise make a new skinframe
3572         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3573         if (skinframe && skinframe->base)
3574                 return skinframe;
3575
3576         skinframe->stain = NULL;
3577         skinframe->merged = NULL;
3578         skinframe->base = NULL;
3579         skinframe->pants = NULL;
3580         skinframe->shirt = NULL;
3581         skinframe->nmap = NULL;
3582         skinframe->gloss = NULL;
3583         skinframe->glow = NULL;
3584         skinframe->fog = NULL;
3585         skinframe->reflect = NULL;
3586         skinframe->hasalpha = false;
3587
3588         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3589         if (!skindata)
3590                 return NULL;
3591
3592         if (developer_loading.integer)
3593                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3594
3595         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3596         if (textureflags & TEXF_ALPHA)
3597         {
3598                 for (i = 0;i < width * height;i++)
3599                 {
3600                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3601                         {
3602                                 skinframe->hasalpha = true;
3603                                 break;
3604                         }
3605                 }
3606                 if (r_loadfog && skinframe->hasalpha)
3607                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3608         }
3609
3610         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3611         //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]);
3612
3613         return skinframe;
3614 }
3615
3616 skinframe_t *R_SkinFrame_LoadMissing(void)
3617 {
3618         skinframe_t *skinframe;
3619
3620         if (cls.state == ca_dedicated)
3621                 return NULL;
3622
3623         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3624         skinframe->stain = NULL;
3625         skinframe->merged = NULL;
3626         skinframe->base = NULL;
3627         skinframe->pants = NULL;
3628         skinframe->shirt = NULL;
3629         skinframe->nmap = NULL;
3630         skinframe->gloss = NULL;
3631         skinframe->glow = NULL;
3632         skinframe->fog = NULL;
3633         skinframe->reflect = NULL;
3634         skinframe->hasalpha = false;
3635
3636         skinframe->avgcolor[0] = rand() / RAND_MAX;
3637         skinframe->avgcolor[1] = rand() / RAND_MAX;
3638         skinframe->avgcolor[2] = rand() / RAND_MAX;
3639         skinframe->avgcolor[3] = 1;
3640
3641         return skinframe;
3642 }
3643
3644 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3645 typedef struct suffixinfo_s
3646 {
3647         const char *suffix;
3648         qboolean flipx, flipy, flipdiagonal;
3649 }
3650 suffixinfo_t;
3651 static suffixinfo_t suffix[3][6] =
3652 {
3653         {
3654                 {"px",   false, false, false},
3655                 {"nx",   false, false, false},
3656                 {"py",   false, false, false},
3657                 {"ny",   false, false, false},
3658                 {"pz",   false, false, false},
3659                 {"nz",   false, false, false}
3660         },
3661         {
3662                 {"posx", false, false, false},
3663                 {"negx", false, false, false},
3664                 {"posy", false, false, false},
3665                 {"negy", false, false, false},
3666                 {"posz", false, false, false},
3667                 {"negz", false, false, false}
3668         },
3669         {
3670                 {"rt",    true, false,  true},
3671                 {"lf",   false,  true,  true},
3672                 {"ft",    true,  true, false},
3673                 {"bk",   false, false, false},
3674                 {"up",    true, false,  true},
3675                 {"dn",    true, false,  true}
3676         }
3677 };
3678
3679 static int componentorder[4] = {0, 1, 2, 3};
3680
3681 rtexture_t *R_LoadCubemap(const char *basename)
3682 {
3683         int i, j, cubemapsize;
3684         unsigned char *cubemappixels, *image_buffer;
3685         rtexture_t *cubemaptexture;
3686         char name[256];
3687         // must start 0 so the first loadimagepixels has no requested width/height
3688         cubemapsize = 0;
3689         cubemappixels = NULL;
3690         cubemaptexture = NULL;
3691         // keep trying different suffix groups (posx, px, rt) until one loads
3692         for (j = 0;j < 3 && !cubemappixels;j++)
3693         {
3694                 // load the 6 images in the suffix group
3695                 for (i = 0;i < 6;i++)
3696                 {
3697                         // generate an image name based on the base and and suffix
3698                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3699                         // load it
3700                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3701                         {
3702                                 // an image loaded, make sure width and height are equal
3703                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3704                                 {
3705                                         // if this is the first image to load successfully, allocate the cubemap memory
3706                                         if (!cubemappixels && image_width >= 1)
3707                                         {
3708                                                 cubemapsize = image_width;
3709                                                 // note this clears to black, so unavailable sides are black
3710                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3711                                         }
3712                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3713                                         if (cubemappixels)
3714                                                 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);
3715                                 }
3716                                 else
3717                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3718                                 // free the image
3719                                 Mem_Free(image_buffer);
3720                         }
3721                 }
3722         }
3723         // if a cubemap loaded, upload it
3724         if (cubemappixels)
3725         {
3726                 if (developer_loading.integer)
3727                         Con_Printf("loading cubemap \"%s\"\n", basename);
3728
3729                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, r_texture_sRGB_cubemap.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3730                 Mem_Free(cubemappixels);
3731         }
3732         else
3733         {
3734                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3735                 if (developer_loading.integer)
3736                 {
3737                         Con_Printf("(tried tried images ");
3738                         for (j = 0;j < 3;j++)
3739                                 for (i = 0;i < 6;i++)
3740                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3741                         Con_Print(" and was unable to find any of them).\n");
3742                 }
3743         }
3744         return cubemaptexture;
3745 }
3746
3747 rtexture_t *R_GetCubemap(const char *basename)
3748 {
3749         int i;
3750         for (i = 0;i < r_texture_numcubemaps;i++)
3751                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3752                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3753         if (i >= MAX_CUBEMAPS)
3754                 return r_texture_whitecube;
3755         r_texture_numcubemaps++;
3756         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3757         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3758         return r_texture_cubemaps[i].texture;
3759 }
3760
3761 void R_FreeCubemaps(void)
3762 {
3763         int i;
3764         for (i = 0;i < r_texture_numcubemaps;i++)
3765         {
3766                 if (developer_loading.integer)
3767                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3768                 if (r_texture_cubemaps[i].texture)
3769                         R_FreeTexture(r_texture_cubemaps[i].texture);
3770         }
3771         r_texture_numcubemaps = 0;
3772 }
3773
3774 void R_Main_FreeViewCache(void)
3775 {
3776         if (r_refdef.viewcache.entityvisible)
3777                 Mem_Free(r_refdef.viewcache.entityvisible);
3778         if (r_refdef.viewcache.world_pvsbits)
3779                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3780         if (r_refdef.viewcache.world_leafvisible)
3781                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3782         if (r_refdef.viewcache.world_surfacevisible)
3783                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3784         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3785 }
3786
3787 void R_Main_ResizeViewCache(void)
3788 {
3789         int numentities = r_refdef.scene.numentities;
3790         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3791         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3792         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3793         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3794         if (r_refdef.viewcache.maxentities < numentities)
3795         {
3796                 r_refdef.viewcache.maxentities = numentities;
3797                 if (r_refdef.viewcache.entityvisible)
3798                         Mem_Free(r_refdef.viewcache.entityvisible);
3799                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3800         }
3801         if (r_refdef.viewcache.world_numclusters != numclusters)
3802         {
3803                 r_refdef.viewcache.world_numclusters = numclusters;
3804                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3805                 if (r_refdef.viewcache.world_pvsbits)
3806                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3807                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3808         }
3809         if (r_refdef.viewcache.world_numleafs != numleafs)
3810         {
3811                 r_refdef.viewcache.world_numleafs = numleafs;
3812                 if (r_refdef.viewcache.world_leafvisible)
3813                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3814                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3815         }
3816         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3817         {
3818                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3819                 if (r_refdef.viewcache.world_surfacevisible)
3820                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3821                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3822         }
3823 }
3824
3825 extern rtexture_t *loadingscreentexture;
3826 void gl_main_start(void)
3827 {
3828         loadingscreentexture = NULL;
3829         r_texture_blanknormalmap = NULL;
3830         r_texture_white = NULL;
3831         r_texture_grey128 = NULL;
3832         r_texture_black = NULL;
3833         r_texture_whitecube = NULL;
3834         r_texture_normalizationcube = NULL;
3835         r_texture_fogattenuation = NULL;
3836         r_texture_fogheighttexture = NULL;
3837         r_texture_gammaramps = NULL;
3838         r_texture_numcubemaps = 0;
3839
3840         r_loaddds = r_texture_dds_load.integer != 0;
3841         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3842
3843         switch(vid.renderpath)
3844         {
3845         case RENDERPATH_GL20:
3846         case RENDERPATH_D3D9:
3847         case RENDERPATH_D3D10:
3848         case RENDERPATH_D3D11:
3849         case RENDERPATH_SOFT:
3850         case RENDERPATH_GLES2:
3851                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3852                 Cvar_SetValueQuick(&gl_combine, 1);
3853                 Cvar_SetValueQuick(&r_glsl, 1);
3854                 r_loadnormalmap = true;
3855                 r_loadgloss = true;
3856                 r_loadfog = false;
3857                 break;
3858         case RENDERPATH_GL13:
3859         case RENDERPATH_GLES1:
3860                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3861                 Cvar_SetValueQuick(&gl_combine, 1);
3862                 Cvar_SetValueQuick(&r_glsl, 0);
3863                 r_loadnormalmap = false;
3864                 r_loadgloss = false;
3865                 r_loadfog = true;
3866                 break;
3867         case RENDERPATH_GL11:
3868                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3869                 Cvar_SetValueQuick(&gl_combine, 0);
3870                 Cvar_SetValueQuick(&r_glsl, 0);
3871                 r_loadnormalmap = false;
3872                 r_loadgloss = false;
3873                 r_loadfog = true;
3874                 break;
3875         }
3876
3877         R_AnimCache_Free();
3878         R_FrameData_Reset();
3879
3880         r_numqueries = 0;
3881         r_maxqueries = 0;
3882         memset(r_queries, 0, sizeof(r_queries));
3883
3884         r_qwskincache = NULL;
3885         r_qwskincache_size = 0;
3886
3887         // due to caching of texture_t references, the collision cache must be reset
3888         Collision_Cache_Reset(true);
3889
3890         // set up r_skinframe loading system for textures
3891         memset(&r_skinframe, 0, sizeof(r_skinframe));
3892         r_skinframe.loadsequence = 1;
3893         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3894
3895         r_main_texturepool = R_AllocTexturePool();
3896         R_BuildBlankTextures();
3897         R_BuildNoTexture();
3898         if (vid.support.arb_texture_cube_map)
3899         {
3900                 R_BuildWhiteCube();
3901                 R_BuildNormalizationCube();
3902         }
3903         r_texture_fogattenuation = NULL;
3904         r_texture_fogheighttexture = NULL;
3905         r_texture_gammaramps = NULL;
3906         //r_texture_fogintensity = NULL;
3907         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3908         memset(&r_waterstate, 0, sizeof(r_waterstate));
3909         r_glsl_permutation = NULL;
3910         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3911         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3912         glslshaderstring = NULL;
3913 #ifdef SUPPORTD3D
3914         r_hlsl_permutation = NULL;
3915         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3916         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3917 #endif
3918         hlslshaderstring = NULL;
3919         memset(&r_svbsp, 0, sizeof (r_svbsp));
3920
3921         r_refdef.fogmasktable_density = 0;
3922 }
3923
3924 void gl_main_shutdown(void)
3925 {
3926         R_AnimCache_Free();
3927         R_FrameData_Reset();
3928
3929         R_Main_FreeViewCache();
3930
3931         switch(vid.renderpath)
3932         {
3933         case RENDERPATH_GL11:
3934         case RENDERPATH_GL13:
3935         case RENDERPATH_GL20:
3936         case RENDERPATH_GLES1:
3937         case RENDERPATH_GLES2:
3938                 if (r_maxqueries)
3939                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3940                 break;
3941         case RENDERPATH_D3D9:
3942                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3943                 break;
3944         case RENDERPATH_D3D10:
3945                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3946                 break;
3947         case RENDERPATH_D3D11:
3948                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3949                 break;
3950         case RENDERPATH_SOFT:
3951                 break;
3952         }
3953
3954         r_numqueries = 0;
3955         r_maxqueries = 0;
3956         memset(r_queries, 0, sizeof(r_queries));
3957
3958         r_qwskincache = NULL;
3959         r_qwskincache_size = 0;
3960
3961         // clear out the r_skinframe state
3962         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3963         memset(&r_skinframe, 0, sizeof(r_skinframe));
3964
3965         if (r_svbsp.nodes)
3966                 Mem_Free(r_svbsp.nodes);
3967         memset(&r_svbsp, 0, sizeof (r_svbsp));
3968         R_FreeTexturePool(&r_main_texturepool);
3969         loadingscreentexture = NULL;
3970         r_texture_blanknormalmap = NULL;
3971         r_texture_white = NULL;
3972         r_texture_grey128 = NULL;
3973         r_texture_black = NULL;
3974         r_texture_whitecube = NULL;
3975         r_texture_normalizationcube = NULL;
3976         r_texture_fogattenuation = NULL;
3977         r_texture_fogheighttexture = NULL;
3978         r_texture_gammaramps = NULL;
3979         r_texture_numcubemaps = 0;
3980         //r_texture_fogintensity = NULL;
3981         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3982         memset(&r_waterstate, 0, sizeof(r_waterstate));
3983         R_GLSL_Restart_f();
3984
3985         r_glsl_permutation = NULL;
3986         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3987         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3988         glslshaderstring = NULL;
3989 #ifdef SUPPORTD3D
3990         r_hlsl_permutation = NULL;
3991         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3992         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3993 #endif
3994         hlslshaderstring = NULL;
3995 }
3996
3997 extern void CL_ParseEntityLump(char *entitystring);
3998 void gl_main_newmap(void)
3999 {
4000         // FIXME: move this code to client
4001         char *entities, entname[MAX_QPATH];
4002         if (r_qwskincache)
4003                 Mem_Free(r_qwskincache);
4004         r_qwskincache = NULL;
4005         r_qwskincache_size = 0;
4006         if (cl.worldmodel)
4007         {
4008                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4009                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4010                 {
4011                         CL_ParseEntityLump(entities);
4012                         Mem_Free(entities);
4013                         return;
4014                 }
4015                 if (cl.worldmodel->brush.entities)
4016                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4017         }
4018         R_Main_FreeViewCache();
4019
4020         R_FrameData_Reset();
4021 }
4022
4023 void GL_Main_Init(void)
4024 {
4025         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4026
4027         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4028         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4029         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4030         if (gamemode == GAME_NEHAHRA)
4031         {
4032                 Cvar_RegisterVariable (&gl_fogenable);
4033                 Cvar_RegisterVariable (&gl_fogdensity);
4034                 Cvar_RegisterVariable (&gl_fogred);
4035                 Cvar_RegisterVariable (&gl_foggreen);
4036                 Cvar_RegisterVariable (&gl_fogblue);
4037                 Cvar_RegisterVariable (&gl_fogstart);
4038                 Cvar_RegisterVariable (&gl_fogend);
4039                 Cvar_RegisterVariable (&gl_skyclip);
4040         }
4041         Cvar_RegisterVariable(&r_motionblur);
4042         Cvar_RegisterVariable(&r_motionblur_maxblur);
4043         Cvar_RegisterVariable(&r_motionblur_bmin);
4044         Cvar_RegisterVariable(&r_motionblur_vmin);
4045         Cvar_RegisterVariable(&r_motionblur_vmax);
4046         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4047         Cvar_RegisterVariable(&r_motionblur_randomize);
4048         Cvar_RegisterVariable(&r_damageblur);
4049         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4050         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4051         Cvar_RegisterVariable(&r_equalize_entities_by);
4052         Cvar_RegisterVariable(&r_equalize_entities_to);
4053         Cvar_RegisterVariable(&r_depthfirst);
4054         Cvar_RegisterVariable(&r_useinfinitefarclip);
4055         Cvar_RegisterVariable(&r_farclip_base);
4056         Cvar_RegisterVariable(&r_farclip_world);
4057         Cvar_RegisterVariable(&r_nearclip);
4058         Cvar_RegisterVariable(&r_deformvertexes);
4059         Cvar_RegisterVariable(&r_transparent);
4060         Cvar_RegisterVariable(&r_showoverdraw);
4061         Cvar_RegisterVariable(&r_showbboxes);
4062         Cvar_RegisterVariable(&r_showsurfaces);
4063         Cvar_RegisterVariable(&r_showtris);
4064         Cvar_RegisterVariable(&r_shownormals);
4065         Cvar_RegisterVariable(&r_showlighting);
4066         Cvar_RegisterVariable(&r_showshadowvolumes);
4067         Cvar_RegisterVariable(&r_showcollisionbrushes);
4068         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4069         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4070         Cvar_RegisterVariable(&r_showdisabledepthtest);
4071         Cvar_RegisterVariable(&r_drawportals);
4072         Cvar_RegisterVariable(&r_drawentities);
4073         Cvar_RegisterVariable(&r_draw2d);
4074         Cvar_RegisterVariable(&r_drawworld);
4075         Cvar_RegisterVariable(&r_cullentities_trace);
4076         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4077         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4078         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4079         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4080         Cvar_RegisterVariable(&r_drawviewmodel);
4081         Cvar_RegisterVariable(&r_drawexteriormodel);
4082         Cvar_RegisterVariable(&r_speeds);
4083         Cvar_RegisterVariable(&r_fullbrights);
4084         Cvar_RegisterVariable(&r_wateralpha);
4085         Cvar_RegisterVariable(&r_dynamic);
4086         Cvar_RegisterVariable(&r_fakelight);
4087         Cvar_RegisterVariable(&r_fakelight_intensity);
4088         Cvar_RegisterVariable(&r_fullbright);
4089         Cvar_RegisterVariable(&r_shadows);
4090         Cvar_RegisterVariable(&r_shadows_darken);
4091         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4092         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4093         Cvar_RegisterVariable(&r_shadows_throwdistance);
4094         Cvar_RegisterVariable(&r_shadows_throwdirection);
4095         Cvar_RegisterVariable(&r_shadows_focus);
4096         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4097         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4098         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4099         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4100         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4101         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4102         Cvar_RegisterVariable(&r_fog_exp2);
4103         Cvar_RegisterVariable(&r_fog_clear);
4104         Cvar_RegisterVariable(&r_drawfog);
4105         Cvar_RegisterVariable(&r_transparentdepthmasking);
4106         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4107         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4108         Cvar_RegisterVariable(&r_texture_dds_load);
4109         Cvar_RegisterVariable(&r_texture_dds_save);
4110         Cvar_RegisterVariable(&r_texture_sRGB_2d);
4111         Cvar_RegisterVariable(&r_texture_sRGB_skin_diffuse);
4112         Cvar_RegisterVariable(&r_texture_sRGB_skin_gloss);
4113         Cvar_RegisterVariable(&r_texture_sRGB_skin_glow);
4114         Cvar_RegisterVariable(&r_texture_sRGB_skin_reflect);
4115         Cvar_RegisterVariable(&r_texture_sRGB_cubemap);
4116         Cvar_RegisterVariable(&r_texture_sRGB_skybox);
4117         Cvar_RegisterVariable(&r_textureunits);
4118         Cvar_RegisterVariable(&gl_combine);
4119         Cvar_RegisterVariable(&r_viewfbo);
4120         Cvar_RegisterVariable(&r_viewscale);
4121         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4122         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4123         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4124         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4125         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4126         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4127         Cvar_RegisterVariable(&r_glsl);
4128         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4129         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4130         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4131         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4132         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4133         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4134         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4135         Cvar_RegisterVariable(&r_glsl_postprocess);
4136         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4137         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4138         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4139         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4140         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4141         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4142         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4143         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4144
4145         Cvar_RegisterVariable(&r_water);
4146         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4147         Cvar_RegisterVariable(&r_water_clippingplanebias);
4148         Cvar_RegisterVariable(&r_water_refractdistort);
4149         Cvar_RegisterVariable(&r_water_reflectdistort);
4150         Cvar_RegisterVariable(&r_water_scissormode);
4151         Cvar_RegisterVariable(&r_lerpsprites);
4152         Cvar_RegisterVariable(&r_lerpmodels);
4153         Cvar_RegisterVariable(&r_lerplightstyles);
4154         Cvar_RegisterVariable(&r_waterscroll);
4155         Cvar_RegisterVariable(&r_bloom);
4156         Cvar_RegisterVariable(&r_bloom_colorscale);
4157         Cvar_RegisterVariable(&r_bloom_brighten);
4158         Cvar_RegisterVariable(&r_bloom_blur);
4159         Cvar_RegisterVariable(&r_bloom_resolution);
4160         Cvar_RegisterVariable(&r_bloom_colorexponent);
4161         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4162         Cvar_RegisterVariable(&r_hdr);
4163         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4164         Cvar_RegisterVariable(&r_hdr_glowintensity);
4165         Cvar_RegisterVariable(&r_hdr_range);
4166         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4167         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4168         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4169         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4170         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4171         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4172         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4173         Cvar_RegisterVariable(&developer_texturelogging);
4174         Cvar_RegisterVariable(&gl_lightmaps);
4175         Cvar_RegisterVariable(&r_test);
4176         Cvar_RegisterVariable(&r_glsl_saturation);
4177         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4178         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4179         Cvar_RegisterVariable(&r_framedatasize);
4180         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4181                 Cvar_SetValue("r_fullbrights", 0);
4182         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4183
4184         Cvar_RegisterVariable(&r_track_sprites);
4185         Cvar_RegisterVariable(&r_track_sprites_flags);
4186         Cvar_RegisterVariable(&r_track_sprites_scalew);
4187         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4188         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4189         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4190         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4191         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4192 }
4193
4194 extern void R_Textures_Init(void);
4195 extern void GL_Draw_Init(void);
4196 extern void GL_Main_Init(void);
4197 extern void R_Shadow_Init(void);
4198 extern void R_Sky_Init(void);
4199 extern void GL_Surf_Init(void);
4200 extern void R_Particles_Init(void);
4201 extern void R_Explosion_Init(void);
4202 extern void gl_backend_init(void);
4203 extern void Sbar_Init(void);
4204 extern void R_LightningBeams_Init(void);
4205 extern void Mod_RenderInit(void);
4206 extern void Font_Init(void);
4207
4208 void Render_Init(void)
4209 {
4210         gl_backend_init();
4211         R_Textures_Init();
4212         GL_Main_Init();
4213         Font_Init();
4214         GL_Draw_Init();
4215         R_Shadow_Init();
4216         R_Sky_Init();
4217         GL_Surf_Init();
4218         Sbar_Init();
4219         R_Particles_Init();
4220         R_Explosion_Init();
4221         R_LightningBeams_Init();
4222         Mod_RenderInit();
4223 }
4224
4225 /*
4226 ===============
4227 GL_Init
4228 ===============
4229 */
4230 extern char *ENGINE_EXTENSIONS;
4231 void GL_Init (void)
4232 {
4233         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4234         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4235         gl_version = (const char *)qglGetString(GL_VERSION);
4236         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4237
4238         if (!gl_extensions)
4239                 gl_extensions = "";
4240         if (!gl_platformextensions)
4241                 gl_platformextensions = "";
4242
4243         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4244         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4245         Con_Printf("GL_VERSION: %s\n", gl_version);
4246         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4247         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4248
4249         VID_CheckExtensions();
4250
4251         // LordHavoc: report supported extensions
4252         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4253
4254         // clear to black (loading plaque will be seen over this)
4255         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4256 }
4257
4258 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4259 {
4260         int i;
4261         mplane_t *p;
4262         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4263         {
4264                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4265                 if (i == 4)
4266                         continue;
4267                 p = r_refdef.view.frustum + i;
4268                 switch(p->signbits)
4269                 {
4270                 default:
4271                 case 0:
4272                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4273                                 return true;
4274                         break;
4275                 case 1:
4276                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4277                                 return true;
4278                         break;
4279                 case 2:
4280                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4281                                 return true;
4282                         break;
4283                 case 3:
4284                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4285                                 return true;
4286                         break;
4287                 case 4:
4288                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4289                                 return true;
4290                         break;
4291                 case 5:
4292                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4293                                 return true;
4294                         break;
4295                 case 6:
4296                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4297                                 return true;
4298                         break;
4299                 case 7:
4300                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4301                                 return true;
4302                         break;
4303                 }
4304         }
4305         return false;
4306 }
4307
4308 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4309 {
4310         int i;
4311         const mplane_t *p;
4312         for (i = 0;i < numplanes;i++)
4313         {
4314                 p = planes + i;
4315                 switch(p->signbits)
4316                 {
4317                 default:
4318                 case 0:
4319                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4320                                 return true;
4321                         break;
4322                 case 1:
4323                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4324                                 return true;
4325                         break;
4326                 case 2:
4327                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4328                                 return true;
4329                         break;
4330                 case 3:
4331                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4332                                 return true;
4333                         break;
4334                 case 4:
4335                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4336                                 return true;
4337                         break;
4338                 case 5:
4339                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4340                                 return true;
4341                         break;
4342                 case 6:
4343                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4344                                 return true;
4345                         break;
4346                 case 7:
4347                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4348                                 return true;
4349                         break;
4350                 }
4351         }
4352         return false;
4353 }
4354
4355 //==================================================================================
4356
4357 // LordHavoc: this stores temporary data used within the same frame
4358
4359 typedef struct r_framedata_mem_s
4360 {
4361         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4362         size_t size; // how much usable space
4363         size_t current; // how much space in use
4364         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4365         size_t wantedsize; // how much space was allocated
4366         unsigned char *data; // start of real data (16byte aligned)
4367 }
4368 r_framedata_mem_t;
4369
4370 static r_framedata_mem_t *r_framedata_mem;
4371
4372 void R_FrameData_Reset(void)
4373 {
4374         while (r_framedata_mem)
4375         {
4376                 r_framedata_mem_t *next = r_framedata_mem->purge;
4377                 Mem_Free(r_framedata_mem);
4378                 r_framedata_mem = next;
4379         }
4380 }
4381
4382 void R_FrameData_Resize(void)
4383 {
4384         size_t wantedsize;
4385         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4386         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4387         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4388         {
4389                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4390                 newmem->wantedsize = wantedsize;
4391                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4392                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4393                 newmem->current = 0;
4394                 newmem->mark = 0;
4395                 newmem->purge = r_framedata_mem;
4396                 r_framedata_mem = newmem;
4397         }
4398 }
4399
4400 void R_FrameData_NewFrame(void)
4401 {
4402         R_FrameData_Resize();
4403         if (!r_framedata_mem)
4404                 return;
4405         // if we ran out of space on the last frame, free the old memory now
4406         while (r_framedata_mem->purge)
4407         {
4408                 // repeatedly remove the second item in the list, leaving only head
4409                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4410                 Mem_Free(r_framedata_mem->purge);
4411                 r_framedata_mem->purge = next;
4412         }
4413         // reset the current mem pointer
4414         r_framedata_mem->current = 0;
4415         r_framedata_mem->mark = 0;
4416 }
4417
4418 void *R_FrameData_Alloc(size_t size)
4419 {
4420         void *data;
4421
4422         // align to 16 byte boundary - the data pointer is already aligned, so we
4423         // only need to ensure the size of every allocation is also aligned
4424         size = (size + 15) & ~15;
4425
4426         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4427         {
4428                 // emergency - we ran out of space, allocate more memory
4429                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4430                 R_FrameData_Resize();
4431         }
4432
4433         data = r_framedata_mem->data + r_framedata_mem->current;
4434         r_framedata_mem->current += size;
4435
4436         // count the usage for stats
4437         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4438         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4439
4440         return (void *)data;
4441 }
4442
4443 void *R_FrameData_Store(size_t size, void *data)
4444 {
4445         void *d = R_FrameData_Alloc(size);
4446         if (d && data)
4447                 memcpy(d, data, size);
4448         return d;
4449 }
4450
4451 void R_FrameData_SetMark(void)
4452 {
4453         if (!r_framedata_mem)
4454                 return;
4455         r_framedata_mem->mark = r_framedata_mem->current;
4456 }
4457
4458 void R_FrameData_ReturnToMark(void)
4459 {
4460         if (!r_framedata_mem)
4461                 return;
4462         r_framedata_mem->current = r_framedata_mem->mark;
4463 }
4464
4465 //==================================================================================
4466
4467 // LordHavoc: animcache originally written by Echon, rewritten since then
4468
4469 /**
4470  * Animation cache prevents re-generating mesh data for an animated model
4471  * multiple times in one frame for lighting, shadowing, reflections, etc.
4472  */
4473
4474 void R_AnimCache_Free(void)
4475 {
4476 }
4477
4478 void R_AnimCache_ClearCache(void)
4479 {
4480         int i;
4481         entity_render_t *ent;
4482
4483         for (i = 0;i < r_refdef.scene.numentities;i++)
4484         {
4485                 ent = r_refdef.scene.entities[i];
4486                 ent->animcache_vertex3f = NULL;
4487                 ent->animcache_normal3f = NULL;
4488                 ent->animcache_svector3f = NULL;
4489                 ent->animcache_tvector3f = NULL;
4490                 ent->animcache_vertexmesh = NULL;
4491                 ent->animcache_vertex3fbuffer = NULL;
4492                 ent->animcache_vertexmeshbuffer = NULL;
4493         }
4494 }
4495
4496 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4497 {
4498         int i;
4499
4500         // check if we need the meshbuffers
4501         if (!vid.useinterleavedarrays)
4502                 return;
4503
4504         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4505                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4506         // TODO: upload vertex3f buffer?
4507         if (ent->animcache_vertexmesh)
4508         {
4509                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4510                 for (i = 0;i < numvertices;i++)
4511                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4512                 if (ent->animcache_svector3f)
4513                         for (i = 0;i < numvertices;i++)
4514                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4515                 if (ent->animcache_tvector3f)
4516                         for (i = 0;i < numvertices;i++)
4517                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4518                 if (ent->animcache_normal3f)
4519                         for (i = 0;i < numvertices;i++)
4520                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4521                 // TODO: upload vertexmeshbuffer?
4522         }
4523 }
4524
4525 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4526 {
4527         dp_model_t *model = ent->model;
4528         int numvertices;
4529         // see if it's already cached this frame
4530         if (ent->animcache_vertex3f)
4531         {
4532                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4533                 if (wantnormals || wanttangents)
4534                 {
4535                         if (ent->animcache_normal3f)
4536                                 wantnormals = false;
4537                         if (ent->animcache_svector3f)
4538                                 wanttangents = false;
4539                         if (wantnormals || wanttangents)
4540                         {
4541                                 numvertices = model->surfmesh.num_vertices;
4542                                 if (wantnormals)
4543                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4544                                 if (wanttangents)
4545                                 {
4546                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4547                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4548                                 }
4549                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4550                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4551                         }
4552                 }
4553         }
4554         else
4555         {
4556                 // see if this ent is worth caching
4557                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4558                         return false;
4559                 // get some memory for this entity and generate mesh data
4560                 numvertices = model->surfmesh.num_vertices;
4561                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4562                 if (wantnormals)
4563                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4564                 if (wanttangents)
4565                 {
4566                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4567                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4568                 }
4569                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4570                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4571         }
4572         return true;
4573 }
4574
4575 void R_AnimCache_CacheVisibleEntities(void)
4576 {
4577         int i;
4578         qboolean wantnormals = true;
4579         qboolean wanttangents = !r_showsurfaces.integer;
4580
4581         switch(vid.renderpath)
4582         {
4583         case RENDERPATH_GL20:
4584         case RENDERPATH_D3D9:
4585         case RENDERPATH_D3D10:
4586         case RENDERPATH_D3D11:
4587         case RENDERPATH_GLES2:
4588                 break;
4589         case RENDERPATH_GL11:
4590         case RENDERPATH_GL13:
4591         case RENDERPATH_GLES1:
4592                 wanttangents = false;
4593                 break;
4594         case RENDERPATH_SOFT:
4595                 break;
4596         }
4597
4598         if (r_shownormals.integer)
4599                 wanttangents = wantnormals = true;
4600
4601         // TODO: thread this
4602         // NOTE: R_PrepareRTLights() also caches entities
4603
4604         for (i = 0;i < r_refdef.scene.numentities;i++)
4605                 if (r_refdef.viewcache.entityvisible[i])
4606                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4607 }
4608
4609 //==================================================================================
4610
4611 static void R_View_UpdateEntityLighting (void)
4612 {
4613         int i;
4614         entity_render_t *ent;
4615         vec3_t tempdiffusenormal, avg;
4616         vec_t f, fa, fd, fdd;
4617         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4618
4619         for (i = 0;i < r_refdef.scene.numentities;i++)
4620         {
4621                 ent = r_refdef.scene.entities[i];
4622
4623                 // skip unseen models
4624                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4625                         continue;
4626
4627                 // skip bsp models
4628                 if (ent->model && ent->model->brush.num_leafs)
4629                 {
4630                         // TODO: use modellight for r_ambient settings on world?
4631                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4632                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4633                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4634                         continue;
4635                 }
4636
4637                 // fetch the lighting from the worldmodel data
4638                 VectorClear(ent->modellight_ambient);
4639                 VectorClear(ent->modellight_diffuse);
4640                 VectorClear(tempdiffusenormal);
4641                 if (ent->flags & RENDER_LIGHT)
4642                 {
4643                         vec3_t org;
4644                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4645
4646                         // complete lightning for lit sprites
4647                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4648                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4649                         {
4650                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4651                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4652                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4653                         }
4654                         else
4655                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4656
4657                         if(ent->flags & RENDER_EQUALIZE)
4658                         {
4659                                 // first fix up ambient lighting...
4660                                 if(r_equalize_entities_minambient.value > 0)
4661                                 {
4662                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4663                                         if(fd > 0)
4664                                         {
4665                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4666                                                 if(fa < r_equalize_entities_minambient.value * fd)
4667                                                 {
4668                                                         // solve:
4669                                                         //   fa'/fd' = minambient
4670                                                         //   fa'+0.25*fd' = fa+0.25*fd
4671                                                         //   ...
4672                                                         //   fa' = fd' * minambient
4673                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4674                                                         //   ...
4675                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4676                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4677                                                         //   ...
4678                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4679                                                         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
4680                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4681                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4682                                                 }
4683                                         }
4684                                 }
4685
4686                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4687                                 {
4688                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4689                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4690                                         f = fa + 0.25 * fd;
4691                                         if(f > 0)
4692                                         {
4693                                                 // adjust brightness and saturation to target
4694                                                 avg[0] = avg[1] = avg[2] = fa / f;
4695                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4696                                                 avg[0] = avg[1] = avg[2] = fd / f;
4697                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4698                                         }
4699                                 }
4700                         }
4701                 }
4702                 else // highly rare
4703                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4704
4705                 // move the light direction into modelspace coordinates for lighting code
4706                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4707                 if(VectorLength2(ent->modellight_lightdir) == 0)
4708                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4709                 VectorNormalize(ent->modellight_lightdir);
4710         }
4711 }
4712
4713 #define MAX_LINEOFSIGHTTRACES 64
4714
4715 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4716 {
4717         int i;
4718         vec3_t boxmins, boxmaxs;
4719         vec3_t start;
4720         vec3_t end;
4721         dp_model_t *model = r_refdef.scene.worldmodel;
4722
4723         if (!model || !model->brush.TraceLineOfSight)
4724                 return true;
4725
4726         // expand the box a little
4727         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4728         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4729         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4730         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4731         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4732         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4733
4734         // return true if eye is inside enlarged box
4735         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4736                 return true;
4737
4738         // try center
4739         VectorCopy(eye, start);
4740         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4741         if (model->brush.TraceLineOfSight(model, start, end))
4742                 return true;
4743
4744         // try various random positions
4745         for (i = 0;i < numsamples;i++)
4746         {
4747                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4748                 if (model->brush.TraceLineOfSight(model, start, end))
4749                         return true;
4750         }
4751
4752         return false;
4753 }
4754
4755
4756 static void R_View_UpdateEntityVisible (void)
4757 {
4758         int i;
4759         int renderimask;
4760         int samples;
4761         entity_render_t *ent;
4762
4763         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4764                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4765                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4766                 :                                                          RENDER_EXTERIORMODEL;
4767         if (!r_drawviewmodel.integer)
4768                 renderimask |= RENDER_VIEWMODEL;
4769         if (!r_drawexteriormodel.integer)
4770                 renderimask |= RENDER_EXTERIORMODEL;
4771         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4772         {
4773                 // worldmodel can check visibility
4774                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4775                 for (i = 0;i < r_refdef.scene.numentities;i++)
4776                 {
4777                         ent = r_refdef.scene.entities[i];
4778                         if (!(ent->flags & renderimask))
4779                         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)))
4780                         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))
4781                                 r_refdef.viewcache.entityvisible[i] = true;
4782                 }
4783         }
4784         else
4785         {
4786                 // no worldmodel or it can't check visibility
4787                 for (i = 0;i < r_refdef.scene.numentities;i++)
4788                 {
4789                         ent = r_refdef.scene.entities[i];
4790                         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));
4791                 }
4792         }
4793         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4794                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4795         {
4796                 for (i = 0;i < r_refdef.scene.numentities;i++)
4797                 {
4798                         if (!r_refdef.viewcache.entityvisible[i])
4799                                 continue;
4800                         ent = r_refdef.scene.entities[i];
4801                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4802                         {
4803                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4804                                 if (samples < 0)
4805                                         continue; // temp entities do pvs only
4806                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4807                                         ent->last_trace_visibility = realtime;
4808                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4809                                         r_refdef.viewcache.entityvisible[i] = 0;
4810                         }
4811                 }
4812         }
4813 }
4814
4815 /// only used if skyrendermasked, and normally returns false
4816 int R_DrawBrushModelsSky (void)
4817 {
4818         int i, sky;
4819         entity_render_t *ent;
4820
4821         sky = false;
4822         for (i = 0;i < r_refdef.scene.numentities;i++)
4823         {
4824                 if (!r_refdef.viewcache.entityvisible[i])
4825                         continue;
4826                 ent = r_refdef.scene.entities[i];
4827                 if (!ent->model || !ent->model->DrawSky)
4828                         continue;
4829                 ent->model->DrawSky(ent);
4830                 sky = true;
4831         }
4832         return sky;
4833 }
4834
4835 static void R_DrawNoModel(entity_render_t *ent);
4836 static void R_DrawModels(void)
4837 {
4838         int i;
4839         entity_render_t *ent;
4840
4841         for (i = 0;i < r_refdef.scene.numentities;i++)
4842         {
4843                 if (!r_refdef.viewcache.entityvisible[i])
4844                         continue;
4845                 ent = r_refdef.scene.entities[i];
4846                 r_refdef.stats.entities++;
4847                 /*
4848                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4849                 {
4850                         vec3_t f, l, u, o;
4851                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4852                         Con_Printf("R_DrawModels\n");
4853                         Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
4854                         Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
4855                         Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
4856                 }
4857                 */
4858                 if (ent->model && ent->model->Draw != NULL)
4859                         ent->model->Draw(ent);
4860                 else
4861                         R_DrawNoModel(ent);
4862         }
4863 }
4864
4865 static void R_DrawModelsDepth(void)
4866 {
4867         int i;
4868         entity_render_t *ent;
4869
4870         for (i = 0;i < r_refdef.scene.numentities;i++)
4871         {
4872                 if (!r_refdef.viewcache.entityvisible[i])
4873                         continue;
4874                 ent = r_refdef.scene.entities[i];
4875                 if (ent->model && ent->model->DrawDepth != NULL)
4876                         ent->model->DrawDepth(ent);
4877         }
4878 }
4879
4880 static void R_DrawModelsDebug(void)
4881 {
4882         int i;
4883         entity_render_t *ent;
4884
4885         for (i = 0;i < r_refdef.scene.numentities;i++)
4886         {
4887                 if (!r_refdef.viewcache.entityvisible[i])
4888                         continue;
4889                 ent = r_refdef.scene.entities[i];
4890                 if (ent->model && ent->model->DrawDebug != NULL)
4891                         ent->model->DrawDebug(ent);
4892         }
4893 }
4894
4895 static void R_DrawModelsAddWaterPlanes(void)
4896 {
4897         int i;
4898         entity_render_t *ent;
4899
4900         for (i = 0;i < r_refdef.scene.numentities;i++)
4901         {
4902                 if (!r_refdef.viewcache.entityvisible[i])
4903                         continue;
4904                 ent = r_refdef.scene.entities[i];
4905                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4906                         ent->model->DrawAddWaterPlanes(ent);
4907         }
4908 }
4909
4910 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4911 {
4912         if (r_hdr_irisadaptation.integer)
4913         {
4914                 vec3_t ambient;
4915                 vec3_t diffuse;
4916                 vec3_t diffusenormal;
4917                 vec_t brightness;
4918                 vec_t goal;
4919                 vec_t adjust;
4920                 vec_t current;
4921                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4922                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4923                 brightness = max(0.0000001f, brightness);
4924                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4925                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4926                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4927                 current = r_hdr_irisadaptation_value.value;
4928                 if (current < goal)
4929                         current = min(current + adjust, goal);
4930                 else if (current > goal)
4931                         current = max(current - adjust, goal);
4932                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4933                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4934         }
4935         else if (r_hdr_irisadaptation_value.value != 1.0f)
4936                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4937 }
4938
4939 static void R_View_SetFrustum(const int *scissor)
4940 {
4941         int i;
4942         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4943         vec3_t forward, left, up, origin, v;
4944
4945         if(scissor)
4946         {
4947                 // flipped x coordinates (because x points left here)
4948                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4949                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4950
4951                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4952                 switch(vid.renderpath)
4953                 {
4954                         case RENDERPATH_D3D9:
4955                         case RENDERPATH_D3D10:
4956                         case RENDERPATH_D3D11:
4957                                 // non-flipped y coordinates
4958                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4959                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4960                                 break;
4961                         case RENDERPATH_SOFT:
4962                         case RENDERPATH_GL11:
4963                         case RENDERPATH_GL13:
4964                         case RENDERPATH_GL20:
4965                         case RENDERPATH_GLES1:
4966                         case RENDERPATH_GLES2:
4967                                 // non-flipped y coordinates
4968                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4969                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4970                                 break;
4971                 }
4972         }
4973
4974         // we can't trust r_refdef.view.forward and friends in reflected scenes
4975         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4976
4977 #if 0
4978         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4979         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4980         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4981         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4982         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4983         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4984         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4985         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4986         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4987         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4988         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4989         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4990 #endif
4991
4992 #if 0
4993         zNear = r_refdef.nearclip;
4994         nudge = 1.0 - 1.0 / (1<<23);
4995         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4996         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4997         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4998         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4999         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5000         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5001         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5002         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5003 #endif
5004
5005
5006
5007 #if 0
5008         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5009         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5010         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5011         r_refdef.view.frustum[0].dist = m[15] - m[12];
5012
5013         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5014         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5015         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5016         r_refdef.view.frustum[1].dist = m[15] + m[12];
5017
5018         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5019         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5020         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5021         r_refdef.view.frustum[2].dist = m[15] - m[13];
5022
5023         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5024         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5025         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5026         r_refdef.view.frustum[3].dist = m[15] + m[13];
5027
5028         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5029         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5030         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5031         r_refdef.view.frustum[4].dist = m[15] - m[14];
5032
5033         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5034         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5035         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5036         r_refdef.view.frustum[5].dist = m[15] + m[14];
5037 #endif
5038
5039         if (r_refdef.view.useperspective)
5040         {
5041                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5042                 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]);
5043                 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]);
5044                 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]);
5045                 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]);
5046
5047                 // then the normals from the corners relative to origin
5048                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5049                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5050                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5051                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5052
5053                 // in a NORMAL view, forward cross left == up
5054                 // in a REFLECTED view, forward cross left == down
5055                 // so our cross products above need to be adjusted for a left handed coordinate system
5056                 CrossProduct(forward, left, v);
5057                 if(DotProduct(v, up) < 0)
5058                 {
5059                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5060                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5061                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5062                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5063                 }
5064
5065                 // Leaving those out was a mistake, those were in the old code, and they
5066                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5067                 // I couldn't reproduce it after adding those normalizations. --blub
5068                 VectorNormalize(r_refdef.view.frustum[0].normal);
5069                 VectorNormalize(r_refdef.view.frustum[1].normal);
5070                 VectorNormalize(r_refdef.view.frustum[2].normal);
5071                 VectorNormalize(r_refdef.view.frustum[3].normal);
5072
5073                 // make the corners absolute
5074                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5075                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5076                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5077                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5078
5079                 // one more normal
5080                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5081
5082                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5083                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5084                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5085                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5086                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5087         }
5088         else
5089         {
5090                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5091                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5092                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5093                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5094                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5095                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5096                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5097                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5098                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5099                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5100         }
5101         r_refdef.view.numfrustumplanes = 5;
5102
5103         if (r_refdef.view.useclipplane)
5104         {
5105                 r_refdef.view.numfrustumplanes = 6;
5106                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5107         }
5108
5109         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5110                 PlaneClassify(r_refdef.view.frustum + i);
5111
5112         // LordHavoc: note to all quake engine coders, Quake had a special case
5113         // for 90 degrees which assumed a square view (wrong), so I removed it,
5114         // Quake2 has it disabled as well.
5115
5116         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5117         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5118         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5119         //PlaneClassify(&frustum[0]);
5120
5121         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5122         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5123         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5124         //PlaneClassify(&frustum[1]);
5125
5126         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5127         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5128         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5129         //PlaneClassify(&frustum[2]);
5130
5131         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5132         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5133         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5134         //PlaneClassify(&frustum[3]);
5135
5136         // nearclip plane
5137         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5138         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5139         //PlaneClassify(&frustum[4]);
5140 }
5141
5142 void R_View_UpdateWithScissor(const int *myscissor)
5143 {
5144         R_Main_ResizeViewCache();
5145         R_View_SetFrustum(myscissor);
5146         R_View_WorldVisibility(r_refdef.view.useclipplane);
5147         R_View_UpdateEntityVisible();
5148         R_View_UpdateEntityLighting();
5149 }
5150
5151 void R_View_Update(void)
5152 {
5153         R_Main_ResizeViewCache();
5154         R_View_SetFrustum(NULL);
5155         R_View_WorldVisibility(r_refdef.view.useclipplane);
5156         R_View_UpdateEntityVisible();
5157         R_View_UpdateEntityLighting();
5158 }
5159
5160 float viewscalefpsadjusted = 1.0f;
5161
5162 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5163 {
5164         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5165         scale = bound(0.03125f, scale, 1.0f);
5166         *outwidth = (int)ceil(width * scale);
5167         *outheight = (int)ceil(height * scale);
5168 }
5169
5170 void R_Mesh_SetMainRenderTargets(void)
5171 {
5172         if (r_bloomstate.fbo_framebuffer)
5173                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5174         else
5175                 R_Mesh_ResetRenderTargets();
5176 }
5177
5178 void R_SetupView(qboolean allowwaterclippingplane)
5179 {
5180         const float *customclipplane = NULL;
5181         float plane[4];
5182         int scaledwidth, scaledheight;
5183         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5184         {
5185                 // LordHavoc: couldn't figure out how to make this approach the
5186                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5187                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5188                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5189                         dist = r_refdef.view.clipplane.dist;
5190                 plane[0] = r_refdef.view.clipplane.normal[0];
5191                 plane[1] = r_refdef.view.clipplane.normal[1];
5192                 plane[2] = r_refdef.view.clipplane.normal[2];
5193                 plane[3] = -dist;
5194                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5195         }
5196
5197         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5198         if (!r_refdef.view.useperspective)
5199                 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);
5200         else if (vid.stencil && r_useinfinitefarclip.integer)
5201                 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);
5202         else
5203                 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);
5204         R_Mesh_SetMainRenderTargets();
5205         R_SetViewport(&r_refdef.view.viewport);
5206         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5207         {
5208                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5209                 float screenplane[4];
5210                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5211                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5212                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5213                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5214                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5215         }
5216 }
5217
5218 void R_EntityMatrix(const matrix4x4_t *matrix)
5219 {
5220         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5221         {
5222                 gl_modelmatrixchanged = false;
5223                 gl_modelmatrix = *matrix;
5224                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5225                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5226                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5227                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5228                 CHECKGLERROR
5229                 switch(vid.renderpath)
5230                 {
5231                 case RENDERPATH_D3D9:
5232 #ifdef SUPPORTD3D
5233                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5234                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5235 #endif
5236                         break;
5237                 case RENDERPATH_D3D10:
5238                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5239                         break;
5240                 case RENDERPATH_D3D11:
5241                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5242                         break;
5243                 case RENDERPATH_GL11:
5244                 case RENDERPATH_GL13:
5245                 case RENDERPATH_GLES1:
5246                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5247                         break;
5248                 case RENDERPATH_SOFT:
5249                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5250                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5251                         break;
5252                 case RENDERPATH_GL20:
5253                 case RENDERPATH_GLES2:
5254                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5255                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5256                         break;
5257                 }
5258         }
5259 }
5260
5261 void R_ResetViewRendering2D(void)
5262 {
5263         r_viewport_t viewport;
5264         DrawQ_Finish();
5265
5266         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5267         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);
5268         R_Mesh_ResetRenderTargets();
5269         R_SetViewport(&viewport);
5270         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5271         GL_Color(1, 1, 1, 1);
5272         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5273         GL_BlendFunc(GL_ONE, GL_ZERO);
5274         GL_ScissorTest(false);
5275         GL_DepthMask(false);
5276         GL_DepthRange(0, 1);
5277         GL_DepthTest(false);
5278         GL_DepthFunc(GL_LEQUAL);
5279         R_EntityMatrix(&identitymatrix);
5280         R_Mesh_ResetTextureState();
5281         GL_PolygonOffset(0, 0);
5282         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5283         switch(vid.renderpath)
5284         {
5285         case RENDERPATH_GL11:
5286         case RENDERPATH_GL13:
5287         case RENDERPATH_GL20:
5288         case RENDERPATH_GLES1:
5289         case RENDERPATH_GLES2:
5290                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5291                 break;
5292         case RENDERPATH_D3D9:
5293         case RENDERPATH_D3D10:
5294         case RENDERPATH_D3D11:
5295         case RENDERPATH_SOFT:
5296                 break;
5297         }
5298         GL_CullFace(GL_NONE);
5299 }
5300
5301 void R_ResetViewRendering3D(void)
5302 {
5303         DrawQ_Finish();
5304
5305         R_SetupView(true);
5306         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5307         GL_Color(1, 1, 1, 1);
5308         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5309         GL_BlendFunc(GL_ONE, GL_ZERO);
5310         GL_ScissorTest(true);
5311         GL_DepthMask(true);
5312         GL_DepthRange(0, 1);
5313         GL_DepthTest(true);
5314         GL_DepthFunc(GL_LEQUAL);
5315         R_EntityMatrix(&identitymatrix);
5316         R_Mesh_ResetTextureState();
5317         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5318         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5319         switch(vid.renderpath)
5320         {
5321         case RENDERPATH_GL11:
5322         case RENDERPATH_GL13:
5323         case RENDERPATH_GL20:
5324         case RENDERPATH_GLES1:
5325         case RENDERPATH_GLES2:
5326                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5327                 break;
5328         case RENDERPATH_D3D9:
5329         case RENDERPATH_D3D10:
5330         case RENDERPATH_D3D11:
5331         case RENDERPATH_SOFT:
5332                 break;
5333         }
5334         GL_CullFace(r_refdef.view.cullface_back);
5335 }
5336
5337 /*
5338 ================
5339 R_RenderView_UpdateViewVectors
5340 ================
5341 */
5342 static void R_RenderView_UpdateViewVectors(void)
5343 {
5344         // break apart the view matrix into vectors for various purposes
5345         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5346         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5347         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5348         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5349         // make an inverted copy of the view matrix for tracking sprites
5350         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5351 }
5352
5353 void R_RenderScene(void);
5354 void R_RenderWaterPlanes(void);
5355
5356 static void R_Water_StartFrame(void)
5357 {
5358         int i;
5359         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5360         r_waterstate_waterplane_t *p;
5361
5362         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5363                 return;
5364
5365         switch(vid.renderpath)
5366         {
5367         case RENDERPATH_GL20:
5368         case RENDERPATH_D3D9:
5369         case RENDERPATH_D3D10:
5370         case RENDERPATH_D3D11:
5371         case RENDERPATH_SOFT:
5372         case RENDERPATH_GLES2:
5373                 break;
5374         case RENDERPATH_GL11:
5375         case RENDERPATH_GL13:
5376         case RENDERPATH_GLES1:
5377                 return;
5378         }
5379
5380         // set waterwidth and waterheight to the water resolution that will be
5381         // used (often less than the screen resolution for faster rendering)
5382         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5383         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5384
5385         // calculate desired texture sizes
5386         // can't use water if the card does not support the texture size
5387         if (!r_water.integer || r_showsurfaces.integer)
5388                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5389         else if (vid.support.arb_texture_non_power_of_two)
5390         {
5391                 texturewidth = waterwidth;
5392                 textureheight = waterheight;
5393                 camerawidth = waterwidth;
5394                 cameraheight = waterheight;
5395         }
5396         else
5397         {
5398                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5399                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5400                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5401                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5402         }
5403
5404         // allocate textures as needed
5405         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5406         {
5407                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5408                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5409                 {
5410                         if (p->texture_refraction)
5411                                 R_FreeTexture(p->texture_refraction);
5412                         p->texture_refraction = NULL;
5413                         if (p->texture_reflection)
5414                                 R_FreeTexture(p->texture_reflection);
5415                         p->texture_reflection = NULL;
5416                         if (p->texture_camera)
5417                                 R_FreeTexture(p->texture_camera);
5418                         p->texture_camera = NULL;
5419                 }
5420                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5421                 r_waterstate.texturewidth = texturewidth;
5422                 r_waterstate.textureheight = textureheight;
5423                 r_waterstate.camerawidth = camerawidth;
5424                 r_waterstate.cameraheight = cameraheight;
5425         }
5426
5427         if (r_waterstate.texturewidth)
5428         {
5429                 r_waterstate.enabled = true;
5430
5431                 // when doing a reduced render (HDR) we want to use a smaller area
5432                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5433                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5434
5435                 // set up variables that will be used in shader setup
5436                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5437                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5438                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5439                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5440         }
5441
5442         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5443         r_waterstate.numwaterplanes = 0;
5444 }
5445
5446 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5447 {
5448         int triangleindex, planeindex;
5449         const int *e;
5450         vec3_t vert[3];
5451         vec3_t normal;
5452         vec3_t center;
5453         mplane_t plane;
5454         r_waterstate_waterplane_t *p;
5455         texture_t *t = R_GetCurrentTexture(surface->texture);
5456
5457         // just use the first triangle with a valid normal for any decisions
5458         VectorClear(normal);
5459         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5460         {
5461                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5462                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5463                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5464                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5465                 if (VectorLength2(normal) >= 0.001)
5466                         break;
5467         }
5468
5469         VectorCopy(normal, plane.normal);
5470         VectorNormalize(plane.normal);
5471         plane.dist = DotProduct(vert[0], plane.normal);
5472         PlaneClassify(&plane);
5473         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5474         {
5475                 // skip backfaces (except if nocullface is set)
5476                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5477                         return;
5478                 VectorNegate(plane.normal, plane.normal);
5479                 plane.dist *= -1;
5480                 PlaneClassify(&plane);
5481         }
5482
5483
5484         // find a matching plane if there is one
5485         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5486                 if(p->camera_entity == t->camera_entity)
5487                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5488                                 break;
5489         if (planeindex >= r_waterstate.maxwaterplanes)
5490                 return; // nothing we can do, out of planes
5491
5492         // if this triangle does not fit any known plane rendered this frame, add one
5493         if (planeindex >= r_waterstate.numwaterplanes)
5494         {
5495                 // store the new plane
5496                 r_waterstate.numwaterplanes++;
5497                 p->plane = plane;
5498                 // clear materialflags and pvs
5499                 p->materialflags = 0;
5500                 p->pvsvalid = false;
5501                 p->camera_entity = t->camera_entity;
5502                 VectorCopy(surface->mins, p->mins);
5503                 VectorCopy(surface->maxs, p->maxs);
5504         }
5505         else
5506         {
5507                 // merge mins/maxs
5508                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5509                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5510                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5511                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5512                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5513                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5514         }
5515         // merge this surface's materialflags into the waterplane
5516         p->materialflags |= t->currentmaterialflags;
5517         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5518         {
5519                 // merge this surface's PVS into the waterplane
5520                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5521                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5522                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5523                 {
5524                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5525                         p->pvsvalid = true;
5526                 }
5527         }
5528 }
5529
5530 static void R_Water_ProcessPlanes(void)
5531 {
5532         int myscissor[4];
5533         r_refdef_view_t originalview;
5534         r_refdef_view_t myview;
5535         int planeindex;
5536         r_waterstate_waterplane_t *p;
5537         vec3_t visorigin;
5538
5539         originalview = r_refdef.view;
5540
5541         // make sure enough textures are allocated
5542         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5543         {
5544                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5545                 {
5546                         if (!p->texture_refraction)
5547                                 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);
5548                         if (!p->texture_refraction)
5549                                 goto error;
5550                 }
5551                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5552                 {
5553                         if (!p->texture_camera)
5554                                 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);
5555                         if (!p->texture_camera)
5556                                 goto error;
5557                 }
5558
5559                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5560                 {
5561                         if (!p->texture_reflection)
5562                                 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);
5563                         if (!p->texture_reflection)
5564                                 goto error;
5565                 }
5566         }
5567
5568         // render views
5569         r_refdef.view = originalview;
5570         r_refdef.view.showdebug = false;
5571         r_refdef.view.width = r_waterstate.waterwidth;
5572         r_refdef.view.height = r_waterstate.waterheight;
5573         r_refdef.view.useclipplane = true;
5574         myview = r_refdef.view;
5575         r_waterstate.renderingscene = true;
5576         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5577         {
5578                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5579                 {
5580                         r_refdef.view = myview;
5581                         if(r_water_scissormode.integer)
5582                         {
5583                                 R_SetupView(true);
5584                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5585                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5586                         }
5587
5588                         // render reflected scene and copy into texture
5589                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5590                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5591                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5592                         r_refdef.view.clipplane = p->plane;
5593
5594                         // reverse the cullface settings for this render
5595                         r_refdef.view.cullface_front = GL_FRONT;
5596                         r_refdef.view.cullface_back = GL_BACK;
5597                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5598                         {
5599                                 r_refdef.view.usecustompvs = true;
5600                                 if (p->pvsvalid)
5601                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5602                                 else
5603                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5604                         }
5605
5606                         R_ResetViewRendering3D();
5607                         R_ClearScreen(r_refdef.fogenabled);
5608                         if(r_water_scissormode.integer & 2)
5609                                 R_View_UpdateWithScissor(myscissor);
5610                         else
5611                                 R_View_Update();
5612                         if(r_water_scissormode.integer & 1)
5613                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5614                         R_RenderScene();
5615
5616                         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);
5617                 }
5618
5619                 // render the normal view scene and copy into texture
5620                 // (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)
5621                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5622                 {
5623                         r_refdef.view = myview;
5624                         if(r_water_scissormode.integer)
5625                         {
5626                                 R_SetupView(true);
5627                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5628                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5629                         }
5630
5631                         r_waterstate.renderingrefraction = true;
5632
5633                         r_refdef.view.clipplane = p->plane;
5634                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5635                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5636
5637                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5638                         {
5639                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5640                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5641                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5642                                 R_RenderView_UpdateViewVectors();
5643                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5644                                 {
5645                                         r_refdef.view.usecustompvs = true;
5646                                         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);
5647                                 }
5648                         }
5649
5650                         PlaneClassify(&r_refdef.view.clipplane);
5651
5652                         R_ResetViewRendering3D();
5653                         R_ClearScreen(r_refdef.fogenabled);
5654                         if(r_water_scissormode.integer & 2)
5655                                 R_View_UpdateWithScissor(myscissor);
5656                         else
5657                                 R_View_Update();
5658                         if(r_water_scissormode.integer & 1)
5659                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5660                         R_RenderScene();
5661
5662                         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);
5663                         r_waterstate.renderingrefraction = false;
5664                 }
5665                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5666                 {
5667                         r_refdef.view = myview;
5668
5669                         r_refdef.view.clipplane = p->plane;
5670                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5671                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5672
5673                         r_refdef.view.width = r_waterstate.camerawidth;
5674                         r_refdef.view.height = r_waterstate.cameraheight;
5675                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5676                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5677
5678                         if(p->camera_entity)
5679                         {
5680                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5681                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5682                         }
5683
5684                         // note: all of the view is used for displaying... so
5685                         // there is no use in scissoring
5686
5687                         // reverse the cullface settings for this render
5688                         r_refdef.view.cullface_front = GL_FRONT;
5689                         r_refdef.view.cullface_back = GL_BACK;
5690                         // also reverse the view matrix
5691                         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
5692                         R_RenderView_UpdateViewVectors();
5693                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5694                         {
5695                                 r_refdef.view.usecustompvs = true;
5696                                 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);
5697                         }
5698                         
5699                         // camera needs no clipplane
5700                         r_refdef.view.useclipplane = false;
5701
5702                         PlaneClassify(&r_refdef.view.clipplane);
5703
5704                         R_ResetViewRendering3D();
5705                         R_ClearScreen(r_refdef.fogenabled);
5706                         R_View_Update();
5707                         R_RenderScene();
5708
5709                         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);
5710                         r_waterstate.renderingrefraction = false;
5711                 }
5712
5713         }
5714         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5715         r_waterstate.renderingscene = false;
5716         r_refdef.view = originalview;
5717         R_ResetViewRendering3D();
5718         R_ClearScreen(r_refdef.fogenabled);
5719         R_View_Update();
5720         return;
5721 error:
5722         r_refdef.view = originalview;
5723         r_waterstate.renderingscene = false;
5724         Cvar_SetValueQuick(&r_water, 0);
5725         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5726         return;
5727 }
5728
5729 void R_Bloom_StartFrame(void)
5730 {
5731         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5732         int viewwidth, viewheight;
5733         textype_t textype;
5734
5735         if (r_viewscale_fpsscaling.integer)
5736         {
5737                 double actualframetime;
5738                 double targetframetime;
5739                 double adjust;
5740                 actualframetime = r_refdef.lastdrawscreentime;
5741                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5742                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5743                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5744                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5745                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5746                 viewscalefpsadjusted += adjust;
5747                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5748         }
5749         else
5750                 viewscalefpsadjusted = 1.0f;
5751
5752         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5753
5754         switch(vid.renderpath)
5755         {
5756         case RENDERPATH_GL20:
5757         case RENDERPATH_D3D9:
5758         case RENDERPATH_D3D10:
5759         case RENDERPATH_D3D11:
5760         case RENDERPATH_SOFT:
5761         case RENDERPATH_GLES2:
5762                 break;
5763         case RENDERPATH_GL11:
5764         case RENDERPATH_GL13:
5765         case RENDERPATH_GLES1:
5766                 return;
5767         }
5768
5769         // set bloomwidth and bloomheight to the bloom resolution that will be
5770         // used (often less than the screen resolution for faster rendering)
5771         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5772         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5773         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5774         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5775         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5776
5777         // calculate desired texture sizes
5778         if (vid.support.arb_texture_non_power_of_two)
5779         {
5780                 screentexturewidth = vid.width;
5781                 screentextureheight = vid.height;
5782                 bloomtexturewidth = r_bloomstate.bloomwidth;
5783                 bloomtextureheight = r_bloomstate.bloomheight;
5784         }
5785         else
5786         {
5787                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5788                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5789                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5790                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5791         }
5792
5793         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))
5794         {
5795                 Cvar_SetValueQuick(&r_hdr, 0);
5796                 Cvar_SetValueQuick(&r_bloom, 0);
5797                 Cvar_SetValueQuick(&r_motionblur, 0);
5798                 Cvar_SetValueQuick(&r_damageblur, 0);
5799         }
5800
5801         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)
5802                 screentexturewidth = screentextureheight = 0;
5803         if (!r_hdr.integer && !r_bloom.integer)
5804                 bloomtexturewidth = bloomtextureheight = 0;
5805
5806         textype = TEXTYPE_COLORBUFFER;
5807         switch (vid.renderpath)
5808         {
5809         case RENDERPATH_GL20:
5810         case RENDERPATH_GLES2:
5811                 if (vid.support.ext_framebuffer_object)
5812                 {
5813                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5814                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5815                 }
5816                 break;
5817         case RENDERPATH_GL11:
5818         case RENDERPATH_GL13:
5819         case RENDERPATH_GLES1:
5820         case RENDERPATH_D3D9:
5821         case RENDERPATH_D3D10:
5822         case RENDERPATH_D3D11:
5823         case RENDERPATH_SOFT:
5824                 break;
5825         }
5826
5827         // allocate textures as needed
5828         if (r_bloomstate.screentexturewidth != screentexturewidth
5829          || r_bloomstate.screentextureheight != screentextureheight
5830          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5831          || r_bloomstate.bloomtextureheight != bloomtextureheight
5832          || r_bloomstate.texturetype != textype
5833          || r_bloomstate.viewfbo != r_viewfbo.integer)
5834         {
5835                 if (r_bloomstate.texture_bloom)
5836                         R_FreeTexture(r_bloomstate.texture_bloom);
5837                 r_bloomstate.texture_bloom = NULL;
5838                 if (r_bloomstate.texture_screen)
5839                         R_FreeTexture(r_bloomstate.texture_screen);
5840                 r_bloomstate.texture_screen = NULL;
5841                 if (r_bloomstate.fbo_framebuffer)
5842                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5843                 r_bloomstate.fbo_framebuffer = 0;
5844                 if (r_bloomstate.texture_framebuffercolor)
5845                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5846                 r_bloomstate.texture_framebuffercolor = NULL;
5847                 if (r_bloomstate.texture_framebufferdepth)
5848                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5849                 r_bloomstate.texture_framebufferdepth = NULL;
5850                 r_bloomstate.screentexturewidth = screentexturewidth;
5851                 r_bloomstate.screentextureheight = screentextureheight;
5852                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5853                         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);
5854                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5855                 {
5856                         // FIXME: choose depth bits based on a cvar
5857                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5858                         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);
5859                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5860                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5861                         // render depth into one texture and normalmap into the other
5862                         if (qglDrawBuffer)
5863                         {
5864                                 int status;
5865                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5866                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5867                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5868                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5869                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5870                         }
5871                 }
5872                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5873                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5874                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5875                         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);
5876                 r_bloomstate.viewfbo = r_viewfbo.integer;
5877                 r_bloomstate.texturetype = textype;
5878         }
5879
5880         // when doing a reduced render (HDR) we want to use a smaller area
5881         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5882         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5883         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5884         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5885         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5886
5887         // set up a texcoord array for the full resolution screen image
5888         // (we have to keep this around to copy back during final render)
5889         r_bloomstate.screentexcoord2f[0] = 0;
5890         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5891         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5892         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5893         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5894         r_bloomstate.screentexcoord2f[5] = 0;
5895         r_bloomstate.screentexcoord2f[6] = 0;
5896         r_bloomstate.screentexcoord2f[7] = 0;
5897
5898         // set up a texcoord array for the reduced resolution bloom image
5899         // (which will be additive blended over the screen image)
5900         r_bloomstate.bloomtexcoord2f[0] = 0;
5901         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5902         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5903         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5904         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5905         r_bloomstate.bloomtexcoord2f[5] = 0;
5906         r_bloomstate.bloomtexcoord2f[6] = 0;
5907         r_bloomstate.bloomtexcoord2f[7] = 0;
5908
5909         switch(vid.renderpath)
5910         {
5911         case RENDERPATH_GL11:
5912         case RENDERPATH_GL13:
5913         case RENDERPATH_GL20:
5914         case RENDERPATH_SOFT:
5915         case RENDERPATH_GLES1:
5916         case RENDERPATH_GLES2:
5917                 break;
5918         case RENDERPATH_D3D9:
5919         case RENDERPATH_D3D10:
5920         case RENDERPATH_D3D11:
5921                 {
5922                         int i;
5923                         for (i = 0;i < 4;i++)
5924                         {
5925                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5926                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5927                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5928                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5929                         }
5930                 }
5931                 break;
5932         }
5933
5934         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5935         {
5936                 r_bloomstate.enabled = true;
5937                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5938         }
5939
5940         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);
5941
5942         if (r_bloomstate.fbo_framebuffer)
5943                 r_refdef.view.clear = true;
5944 }
5945
5946 void R_Bloom_CopyBloomTexture(float colorscale)
5947 {
5948         r_refdef.stats.bloom++;
5949
5950         // scale down screen texture to the bloom texture size
5951         CHECKGLERROR
5952         R_Mesh_SetMainRenderTargets();
5953         R_SetViewport(&r_bloomstate.viewport);
5954         GL_BlendFunc(GL_ONE, GL_ZERO);
5955         GL_Color(colorscale, colorscale, colorscale, 1);
5956         // 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...
5957         switch(vid.renderpath)
5958         {
5959         case RENDERPATH_GL11:
5960         case RENDERPATH_GL13:
5961         case RENDERPATH_GL20:
5962         case RENDERPATH_GLES1:
5963         case RENDERPATH_GLES2:
5964         case RENDERPATH_SOFT:
5965                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5966                 break;
5967         case RENDERPATH_D3D9:
5968         case RENDERPATH_D3D10:
5969         case RENDERPATH_D3D11:
5970                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5971                 break;
5972         }
5973         // TODO: do boxfilter scale-down in shader?
5974         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5975         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5976         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5977
5978         // we now have a bloom image in the framebuffer
5979         // copy it into the bloom image texture for later processing
5980         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);
5981         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5982 }
5983
5984 void R_Bloom_CopyHDRTexture(void)
5985 {
5986         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);
5987         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5988 }
5989
5990 void R_Bloom_MakeTexture(void)
5991 {
5992         int x, range, dir;
5993         float xoffset, yoffset, r, brighten;
5994
5995         r_refdef.stats.bloom++;
5996
5997         R_ResetViewRendering2D();
5998
5999         // we have a bloom image in the framebuffer
6000         CHECKGLERROR
6001         R_SetViewport(&r_bloomstate.viewport);
6002
6003         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6004         {
6005                 x *= 2;
6006                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6007                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6008                 GL_Color(r,r,r,1);
6009                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6010                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6011                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6012                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6013
6014                 // copy the vertically blurred bloom view to a texture
6015                 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);
6016                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6017         }
6018
6019         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6020         brighten = r_bloom_brighten.value;
6021         if (r_bloomstate.hdr)
6022                 brighten *= r_hdr_range.value;
6023         brighten = sqrt(brighten);
6024         if(range >= 1)
6025                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6026         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6027
6028         for (dir = 0;dir < 2;dir++)
6029         {
6030                 // blend on at multiple vertical offsets to achieve a vertical blur
6031                 // TODO: do offset blends using GLSL
6032                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6033                 GL_BlendFunc(GL_ONE, GL_ZERO);
6034                 for (x = -range;x <= range;x++)
6035                 {
6036                         if (!dir){xoffset = 0;yoffset = x;}
6037                         else {xoffset = x;yoffset = 0;}
6038                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6039                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6040                         // compute a texcoord array with the specified x and y offset
6041                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6042                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6043                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6044                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6045                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6046                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6047                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6048                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6049                         // this r value looks like a 'dot' particle, fading sharply to
6050                         // black at the edges
6051                         // (probably not realistic but looks good enough)
6052                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6053                         //r = brighten/(range*2+1);
6054                         r = brighten / (range * 2 + 1);
6055                         if(range >= 1)
6056                                 r *= (1 - x*x/(float)(range*range));
6057                         GL_Color(r, r, r, 1);
6058                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6059                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6060                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6061                         GL_BlendFunc(GL_ONE, GL_ONE);
6062                 }
6063
6064                 // copy the vertically blurred bloom view to a texture
6065                 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);
6066                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6067         }
6068 }
6069
6070 void R_HDR_RenderBloomTexture(void)
6071 {
6072         int oldwidth, oldheight;
6073         float oldcolorscale;
6074         qboolean oldwaterstate;
6075
6076         oldwaterstate = r_waterstate.enabled;
6077         oldcolorscale = r_refdef.view.colorscale;
6078         oldwidth = r_refdef.view.width;
6079         oldheight = r_refdef.view.height;
6080         r_refdef.view.width = r_bloomstate.bloomwidth;
6081         r_refdef.view.height = r_bloomstate.bloomheight;
6082
6083         if(r_hdr.integer < 2)
6084                 r_waterstate.enabled = false;
6085
6086         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6087         // TODO: add exposure compensation features
6088         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6089
6090         r_refdef.view.showdebug = false;
6091         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6092
6093         R_ResetViewRendering3D();
6094
6095         R_ClearScreen(r_refdef.fogenabled);
6096         if (r_timereport_active)
6097                 R_TimeReport("HDRclear");
6098
6099         R_View_Update();
6100         if (r_timereport_active)
6101                 R_TimeReport("visibility");
6102
6103         // only do secondary renders with HDR if r_hdr is 2 or higher
6104         r_waterstate.numwaterplanes = 0;
6105         if (r_waterstate.enabled)
6106                 R_RenderWaterPlanes();
6107
6108         r_refdef.view.showdebug = true;
6109         R_RenderScene();
6110         r_waterstate.numwaterplanes = 0;
6111
6112         R_ResetViewRendering2D();
6113
6114         R_Bloom_CopyHDRTexture();
6115         R_Bloom_MakeTexture();
6116
6117         // restore the view settings
6118         r_waterstate.enabled = oldwaterstate;
6119         r_refdef.view.width = oldwidth;
6120         r_refdef.view.height = oldheight;
6121         r_refdef.view.colorscale = oldcolorscale;
6122
6123         R_ResetViewRendering3D();
6124
6125         R_ClearScreen(r_refdef.fogenabled);
6126         if (r_timereport_active)
6127                 R_TimeReport("viewclear");
6128 }
6129
6130 static void R_BlendView(void)
6131 {
6132         unsigned int permutation;
6133         float uservecs[4][4];
6134
6135         switch (vid.renderpath)
6136         {
6137         case RENDERPATH_GL20:
6138         case RENDERPATH_D3D9:
6139         case RENDERPATH_D3D10:
6140         case RENDERPATH_D3D11:
6141         case RENDERPATH_SOFT:
6142         case RENDERPATH_GLES2:
6143                 permutation =
6144                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6145                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6146                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6147                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6148                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6149
6150                 if (r_bloomstate.texture_screen)
6151                 {
6152                         // make sure the buffer is available
6153                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6154
6155                         R_ResetViewRendering2D();
6156                         R_Mesh_SetMainRenderTargets();
6157
6158                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6159                         {
6160                                 // declare variables
6161                                 float speed;
6162                                 static float avgspeed;
6163
6164                                 speed = VectorLength(cl.movement_velocity);
6165
6166                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6167                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6168
6169                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6170                                 speed = bound(0, speed, 1);
6171                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6172
6173                                 // calculate values into a standard alpha
6174                                 cl.motionbluralpha = 1 - exp(-
6175                                                 (
6176                                                  (r_motionblur.value * speed / 80)
6177                                                  +
6178                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6179                                                 )
6180                                                 /
6181                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6182                                            );
6183
6184                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6185                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6186                                 // apply the blur
6187                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6188                                 {
6189                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6190                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6191                                         switch(vid.renderpath)
6192                                         {
6193                                         case RENDERPATH_GL11:
6194                                         case RENDERPATH_GL13:
6195                                         case RENDERPATH_GL20:
6196                                         case RENDERPATH_GLES1:
6197                                         case RENDERPATH_GLES2:
6198                                         case RENDERPATH_SOFT:
6199                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6200                                                 break;
6201                                         case RENDERPATH_D3D9:
6202                                         case RENDERPATH_D3D10:
6203                                         case RENDERPATH_D3D11:
6204                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6205                                                 break;
6206                                         }
6207                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6208                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6209                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6210                                 }
6211                         }
6212
6213                         // copy view into the screen texture
6214                         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);
6215                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6216                 }
6217                 else if (!r_bloomstate.texture_bloom)
6218                 {
6219                         // we may still have to do view tint...
6220                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6221                         {
6222                                 // apply a color tint to the whole view
6223                                 R_ResetViewRendering2D();
6224                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6225                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6226                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6227                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6228                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6229                         }
6230                         break; // no screen processing, no bloom, skip it
6231                 }
6232
6233                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6234                 {
6235                         // render simple bloom effect
6236                         // copy the screen and shrink it and darken it for the bloom process
6237                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6238                         // make the bloom texture
6239                         R_Bloom_MakeTexture();
6240                 }
6241
6242 #if _MSC_VER >= 1400
6243 #define sscanf sscanf_s
6244 #endif
6245                 memset(uservecs, 0, sizeof(uservecs));
6246                 if (r_glsl_postprocess_uservec1_enable.integer)
6247                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6248                 if (r_glsl_postprocess_uservec2_enable.integer)
6249                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6250                 if (r_glsl_postprocess_uservec3_enable.integer)
6251                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6252                 if (r_glsl_postprocess_uservec4_enable.integer)
6253                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6254
6255                 R_ResetViewRendering2D();
6256                 GL_Color(1, 1, 1, 1);
6257                 GL_BlendFunc(GL_ONE, GL_ZERO);
6258
6259                 switch(vid.renderpath)
6260                 {
6261                 case RENDERPATH_GL20:
6262                 case RENDERPATH_GLES2:
6263                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6264                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6265                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6266                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6267                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6268                         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]);
6269                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6270                         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]);
6271                         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]);
6272                         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]);
6273                         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]);
6274                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6275                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6276                         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);
6277                         break;
6278                 case RENDERPATH_D3D9:
6279 #ifdef SUPPORTD3D
6280                         // 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...
6281                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6282                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6283                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6284                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6285                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6286                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6287                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6288                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6289                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6290                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6291                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6292                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6293                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6294                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6295 #endif
6296                         break;
6297                 case RENDERPATH_D3D10:
6298                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6299                         break;
6300                 case RENDERPATH_D3D11:
6301                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6302                         break;
6303                 case RENDERPATH_SOFT:
6304                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6305                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6306                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6307                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6308                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6309                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6310                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6311                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6312                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6313                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6314                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6315                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6316                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6317                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6318                         break;
6319                 default:
6320                         break;
6321                 }
6322                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6323                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6324                 break;
6325         case RENDERPATH_GL11:
6326         case RENDERPATH_GL13:
6327         case RENDERPATH_GLES1:
6328                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6329                 {
6330                         // apply a color tint to the whole view
6331                         R_ResetViewRendering2D();
6332                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6333                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6334                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6335                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6336                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6337                 }
6338                 break;
6339         }
6340 }
6341
6342 matrix4x4_t r_waterscrollmatrix;
6343
6344 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6345 {
6346         if (r_refdef.fog_density)
6347         {
6348                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6349                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6350                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6351
6352                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6353                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6354                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6355                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6356
6357                 {
6358                         vec3_t fogvec;
6359                         VectorCopy(r_refdef.fogcolor, fogvec);
6360                         //   color.rgb *= ContrastBoost * SceneBrightness;
6361                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6362                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6363                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6364                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6365                 }
6366         }
6367 }
6368
6369 void R_UpdateVariables(void)
6370 {
6371         R_Textures_Frame();
6372
6373         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6374
6375         r_refdef.farclip = r_farclip_base.value;
6376         if (r_refdef.scene.worldmodel)
6377                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6378         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6379
6380         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6381                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6382         r_refdef.polygonfactor = 0;
6383         r_refdef.polygonoffset = 0;
6384         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6385         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6386
6387         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6388         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6389         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6390         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6391         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6392         if (FAKELIGHT_ENABLED)
6393         {
6394                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6395         }
6396         if (r_showsurfaces.integer)
6397         {
6398                 r_refdef.scene.rtworld = false;
6399                 r_refdef.scene.rtworldshadows = false;
6400                 r_refdef.scene.rtdlight = false;
6401                 r_refdef.scene.rtdlightshadows = false;
6402                 r_refdef.lightmapintensity = 0;
6403         }
6404
6405         if (gamemode == GAME_NEHAHRA)
6406         {
6407                 if (gl_fogenable.integer)
6408                 {
6409                         r_refdef.oldgl_fogenable = true;
6410                         r_refdef.fog_density = gl_fogdensity.value;
6411                         r_refdef.fog_red = gl_fogred.value;
6412                         r_refdef.fog_green = gl_foggreen.value;
6413                         r_refdef.fog_blue = gl_fogblue.value;
6414                         r_refdef.fog_alpha = 1;
6415                         r_refdef.fog_start = 0;
6416                         r_refdef.fog_end = gl_skyclip.value;
6417                         r_refdef.fog_height = 1<<30;
6418                         r_refdef.fog_fadedepth = 128;
6419                 }
6420                 else if (r_refdef.oldgl_fogenable)
6421                 {
6422                         r_refdef.oldgl_fogenable = false;
6423                         r_refdef.fog_density = 0;
6424                         r_refdef.fog_red = 0;
6425                         r_refdef.fog_green = 0;
6426                         r_refdef.fog_blue = 0;
6427                         r_refdef.fog_alpha = 0;
6428                         r_refdef.fog_start = 0;
6429                         r_refdef.fog_end = 0;
6430                         r_refdef.fog_height = 1<<30;
6431                         r_refdef.fog_fadedepth = 128;
6432                 }
6433         }
6434
6435         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6436         r_refdef.fog_start = max(0, r_refdef.fog_start);
6437         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6438
6439         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6440
6441         if (r_refdef.fog_density && r_drawfog.integer)
6442         {
6443                 r_refdef.fogenabled = true;
6444                 // this is the point where the fog reaches 0.9986 alpha, which we
6445                 // consider a good enough cutoff point for the texture
6446                 // (0.9986 * 256 == 255.6)
6447                 if (r_fog_exp2.integer)
6448                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6449                 else
6450                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6451                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6452                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6453                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6454                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6455                         R_BuildFogHeightTexture();
6456                 // fog color was already set
6457                 // update the fog texture
6458                 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)
6459                         R_BuildFogTexture();
6460                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6461                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6462         }
6463         else
6464                 r_refdef.fogenabled = false;
6465
6466         switch(vid.renderpath)
6467         {
6468         case RENDERPATH_GL20:
6469         case RENDERPATH_D3D9:
6470         case RENDERPATH_D3D10:
6471         case RENDERPATH_D3D11:
6472         case RENDERPATH_SOFT:
6473         case RENDERPATH_GLES2:
6474                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6475                 {
6476                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6477                         {
6478                                 // build GLSL gamma texture
6479 #define RAMPWIDTH 256
6480                                 unsigned short ramp[RAMPWIDTH * 3];
6481                                 unsigned char rampbgr[RAMPWIDTH][4];
6482                                 int i;
6483
6484                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6485
6486                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6487                                 for(i = 0; i < RAMPWIDTH; ++i)
6488                                 {
6489                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6490                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6491                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6492                                         rampbgr[i][3] = 0;
6493                                 }
6494                                 if (r_texture_gammaramps)
6495                                 {
6496                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6497                                 }
6498                                 else
6499                                 {
6500                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6501                                 }
6502                         }
6503                 }
6504                 else
6505                 {
6506                         // remove GLSL gamma texture
6507                 }
6508                 break;
6509         case RENDERPATH_GL11:
6510         case RENDERPATH_GL13:
6511         case RENDERPATH_GLES1:
6512                 break;
6513         }
6514 }
6515
6516 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6517 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6518 /*
6519 ================
6520 R_SelectScene
6521 ================
6522 */
6523 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6524         if( scenetype != r_currentscenetype ) {
6525                 // store the old scenetype
6526                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6527                 r_currentscenetype = scenetype;
6528                 // move in the new scene
6529                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6530         }
6531 }
6532
6533 /*
6534 ================
6535 R_GetScenePointer
6536 ================
6537 */
6538 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6539 {
6540         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6541         if( scenetype == r_currentscenetype ) {
6542                 return &r_refdef.scene;
6543         } else {
6544                 return &r_scenes_store[ scenetype ];
6545         }
6546 }
6547
6548 /*
6549 ================
6550 R_RenderView
6551 ================
6552 */
6553 int dpsoftrast_test;
6554 void R_RenderView(void)
6555 {
6556         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6557
6558         dpsoftrast_test = r_test.integer;
6559
6560         if (r_timereport_active)
6561                 R_TimeReport("start");
6562         r_textureframe++; // used only by R_GetCurrentTexture
6563         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6564
6565         if(R_CompileShader_CheckStaticParms())
6566                 R_GLSL_Restart_f();
6567
6568         if (!r_drawentities.integer)
6569                 r_refdef.scene.numentities = 0;
6570
6571         R_AnimCache_ClearCache();
6572         R_FrameData_NewFrame();
6573
6574         /* adjust for stereo display */
6575         if(R_Stereo_Active())
6576         {
6577                 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);
6578                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6579         }
6580
6581         if (r_refdef.view.isoverlay)
6582         {
6583                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6584                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6585                 R_TimeReport("depthclear");
6586
6587                 r_refdef.view.showdebug = false;
6588
6589                 r_waterstate.enabled = false;
6590                 r_waterstate.numwaterplanes = 0;
6591
6592                 R_RenderScene();
6593
6594                 r_refdef.view.matrix = originalmatrix;
6595
6596                 CHECKGLERROR
6597                 return;
6598         }
6599
6600         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6601         {
6602                 r_refdef.view.matrix = originalmatrix;
6603                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6604         }
6605
6606         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6607
6608         R_RenderView_UpdateViewVectors();
6609
6610         R_Shadow_UpdateWorldLightSelection();
6611
6612         R_Bloom_StartFrame();
6613         R_Water_StartFrame();
6614
6615         CHECKGLERROR
6616         if (r_timereport_active)
6617                 R_TimeReport("viewsetup");
6618
6619         R_ResetViewRendering3D();
6620
6621         if (r_refdef.view.clear || r_refdef.fogenabled)
6622         {
6623                 R_ClearScreen(r_refdef.fogenabled);
6624                 if (r_timereport_active)
6625                         R_TimeReport("viewclear");
6626         }
6627         r_refdef.view.clear = true;
6628
6629         // this produces a bloom texture to be used in R_BlendView() later
6630         if (r_bloomstate.hdr)
6631         {
6632                 R_HDR_RenderBloomTexture();
6633                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6634                 r_textureframe++; // used only by R_GetCurrentTexture
6635         }
6636
6637         r_refdef.view.showdebug = true;
6638
6639         R_View_Update();
6640         if (r_timereport_active)
6641                 R_TimeReport("visibility");
6642
6643         r_waterstate.numwaterplanes = 0;
6644         if (r_waterstate.enabled)
6645                 R_RenderWaterPlanes();
6646
6647         R_RenderScene();
6648         r_waterstate.numwaterplanes = 0;
6649
6650         R_BlendView();
6651         if (r_timereport_active)
6652                 R_TimeReport("blendview");
6653
6654         GL_Scissor(0, 0, vid.width, vid.height);
6655         GL_ScissorTest(false);
6656
6657         r_refdef.view.matrix = originalmatrix;
6658
6659         CHECKGLERROR
6660 }
6661
6662 void R_RenderWaterPlanes(void)
6663 {
6664         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6665         {
6666                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6667                 if (r_timereport_active)
6668                         R_TimeReport("waterworld");
6669         }
6670
6671         // don't let sound skip if going slow
6672         if (r_refdef.scene.extraupdate)
6673                 S_ExtraUpdate ();
6674
6675         R_DrawModelsAddWaterPlanes();
6676         if (r_timereport_active)
6677                 R_TimeReport("watermodels");
6678
6679         if (r_waterstate.numwaterplanes)
6680         {
6681                 R_Water_ProcessPlanes();
6682                 if (r_timereport_active)
6683                         R_TimeReport("waterscenes");
6684         }
6685 }
6686
6687 extern void R_DrawLightningBeams (void);
6688 extern void VM_CL_AddPolygonsToMeshQueue (void);
6689 extern void R_DrawPortals (void);
6690 extern cvar_t cl_locs_show;
6691 static void R_DrawLocs(void);
6692 static void R_DrawEntityBBoxes(void);
6693 static void R_DrawModelDecals(void);
6694 extern void R_DrawModelShadows(void);
6695 extern void R_DrawModelShadowMaps(void);
6696 extern cvar_t cl_decals_newsystem;
6697 extern qboolean r_shadow_usingdeferredprepass;
6698 void R_RenderScene(void)
6699 {
6700         qboolean shadowmapping = false;
6701
6702         if (r_timereport_active)
6703                 R_TimeReport("beginscene");
6704
6705         r_refdef.stats.renders++;
6706
6707         R_UpdateFogColor();
6708
6709         // don't let sound skip if going slow
6710         if (r_refdef.scene.extraupdate)
6711                 S_ExtraUpdate ();
6712
6713         R_MeshQueue_BeginScene();
6714
6715         R_SkyStartFrame();
6716
6717         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);
6718
6719         if (r_timereport_active)
6720                 R_TimeReport("skystartframe");
6721
6722         if (cl.csqc_vidvars.drawworld)
6723         {
6724                 // don't let sound skip if going slow
6725                 if (r_refdef.scene.extraupdate)
6726                         S_ExtraUpdate ();
6727
6728                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6729                 {
6730                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6731                         if (r_timereport_active)
6732                                 R_TimeReport("worldsky");
6733                 }
6734
6735                 if (R_DrawBrushModelsSky() && r_timereport_active)
6736                         R_TimeReport("bmodelsky");
6737
6738                 if (skyrendermasked && skyrenderlater)
6739                 {
6740                         // we have to force off the water clipping plane while rendering sky
6741                         R_SetupView(false);
6742                         R_Sky();
6743                         R_SetupView(true);
6744                         if (r_timereport_active)
6745                                 R_TimeReport("sky");
6746                 }
6747         }
6748
6749         R_AnimCache_CacheVisibleEntities();
6750         if (r_timereport_active)
6751                 R_TimeReport("animation");
6752
6753         R_Shadow_PrepareLights();
6754         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6755                 R_Shadow_PrepareModelShadows();
6756         if (r_timereport_active)
6757                 R_TimeReport("preparelights");
6758
6759         if (R_Shadow_ShadowMappingEnabled())
6760                 shadowmapping = true;
6761
6762         if (r_shadow_usingdeferredprepass)
6763                 R_Shadow_DrawPrepass();
6764
6765         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6766         {
6767                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6768                 if (r_timereport_active)
6769                         R_TimeReport("worlddepth");
6770         }
6771         if (r_depthfirst.integer >= 2)
6772         {
6773                 R_DrawModelsDepth();
6774                 if (r_timereport_active)
6775                         R_TimeReport("modeldepth");
6776         }
6777
6778         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6779         {
6780                 R_DrawModelShadowMaps();
6781                 R_ResetViewRendering3D();
6782                 // don't let sound skip if going slow
6783                 if (r_refdef.scene.extraupdate)
6784                         S_ExtraUpdate ();
6785         }
6786
6787         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6788         {
6789                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6790                 if (r_timereport_active)
6791                         R_TimeReport("world");
6792         }
6793
6794         // don't let sound skip if going slow
6795         if (r_refdef.scene.extraupdate)
6796                 S_ExtraUpdate ();
6797
6798         R_DrawModels();
6799         if (r_timereport_active)
6800                 R_TimeReport("models");
6801
6802         // don't let sound skip if going slow
6803         if (r_refdef.scene.extraupdate)
6804                 S_ExtraUpdate ();
6805
6806         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6807         {
6808                 R_DrawModelShadows();
6809                 R_ResetViewRendering3D();
6810                 // don't let sound skip if going slow
6811                 if (r_refdef.scene.extraupdate)
6812                         S_ExtraUpdate ();
6813         }
6814
6815         if (!r_shadow_usingdeferredprepass)
6816         {
6817                 R_Shadow_DrawLights();
6818                 if (r_timereport_active)
6819                         R_TimeReport("rtlights");
6820         }
6821
6822         // don't let sound skip if going slow
6823         if (r_refdef.scene.extraupdate)
6824                 S_ExtraUpdate ();
6825
6826         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6827         {
6828                 R_DrawModelShadows();
6829                 R_ResetViewRendering3D();
6830                 // don't let sound skip if going slow
6831                 if (r_refdef.scene.extraupdate)
6832                         S_ExtraUpdate ();
6833         }
6834
6835         if (cl.csqc_vidvars.drawworld)
6836         {
6837                 if (cl_decals_newsystem.integer)
6838                 {
6839                         R_DrawModelDecals();
6840                         if (r_timereport_active)
6841                                 R_TimeReport("modeldecals");
6842                 }
6843                 else
6844                 {
6845                         R_DrawDecals();
6846                         if (r_timereport_active)
6847                                 R_TimeReport("decals");
6848                 }
6849
6850                 R_DrawParticles();
6851                 if (r_timereport_active)
6852                         R_TimeReport("particles");
6853
6854                 R_DrawExplosions();
6855                 if (r_timereport_active)
6856                         R_TimeReport("explosions");
6857
6858                 R_DrawLightningBeams();
6859                 if (r_timereport_active)
6860                         R_TimeReport("lightning");
6861         }
6862
6863         VM_CL_AddPolygonsToMeshQueue();
6864
6865         if (r_refdef.view.showdebug)
6866         {
6867                 if (cl_locs_show.integer)
6868                 {
6869                         R_DrawLocs();
6870                         if (r_timereport_active)
6871                                 R_TimeReport("showlocs");
6872                 }
6873
6874                 if (r_drawportals.integer)
6875                 {
6876                         R_DrawPortals();
6877                         if (r_timereport_active)
6878                                 R_TimeReport("portals");
6879                 }
6880
6881                 if (r_showbboxes.value > 0)
6882                 {
6883                         R_DrawEntityBBoxes();
6884                         if (r_timereport_active)
6885                                 R_TimeReport("bboxes");
6886                 }
6887         }
6888
6889         if (r_transparent.integer)
6890         {
6891                 R_MeshQueue_RenderTransparent();
6892                 if (r_timereport_active)
6893                         R_TimeReport("drawtrans");
6894         }
6895
6896         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))
6897         {
6898                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6899                 if (r_timereport_active)
6900                         R_TimeReport("worlddebug");
6901                 R_DrawModelsDebug();
6902                 if (r_timereport_active)
6903                         R_TimeReport("modeldebug");
6904         }
6905
6906         if (cl.csqc_vidvars.drawworld)
6907         {
6908                 R_Shadow_DrawCoronas();
6909                 if (r_timereport_active)
6910                         R_TimeReport("coronas");
6911         }
6912
6913 #if 0
6914         {
6915                 GL_DepthTest(false);
6916                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6917                 GL_Color(1, 1, 1, 1);
6918                 qglBegin(GL_POLYGON);
6919                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6920                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6921                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6922                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6923                 qglEnd();
6924                 qglBegin(GL_POLYGON);
6925                 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]);
6926                 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]);
6927                 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]);
6928                 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]);
6929                 qglEnd();
6930                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6931         }
6932 #endif
6933
6934         // don't let sound skip if going slow
6935         if (r_refdef.scene.extraupdate)
6936                 S_ExtraUpdate ();
6937
6938         R_ResetViewRendering2D();
6939 }
6940
6941 static const unsigned short bboxelements[36] =
6942 {
6943         5, 1, 3, 5, 3, 7,
6944         6, 2, 0, 6, 0, 4,
6945         7, 3, 2, 7, 2, 6,
6946         4, 0, 1, 4, 1, 5,
6947         4, 5, 7, 4, 7, 6,
6948         1, 0, 2, 1, 2, 3,
6949 };
6950
6951 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6952 {
6953         int i;
6954         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6955
6956         RSurf_ActiveWorldEntity();
6957
6958         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6959         GL_DepthMask(false);
6960         GL_DepthRange(0, 1);
6961         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6962 //      R_Mesh_ResetTextureState();
6963
6964         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6965         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6966         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6967         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6968         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6969         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6970         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6971         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6972         R_FillColors(color4f, 8, cr, cg, cb, ca);
6973         if (r_refdef.fogenabled)
6974         {
6975                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6976                 {
6977                         f1 = RSurf_FogVertex(v);
6978                         f2 = 1 - f1;
6979                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6980                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6981                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6982                 }
6983         }
6984         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6985         R_Mesh_ResetTextureState();
6986         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6987         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6988 }
6989
6990 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6991 {
6992         int i;
6993         float color[4];
6994         prvm_edict_t *edict;
6995         prvm_prog_t *prog_save = prog;
6996
6997         // this function draws bounding boxes of server entities
6998         if (!sv.active)
6999                 return;
7000
7001         GL_CullFace(GL_NONE);
7002         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7003
7004         prog = 0;
7005         SV_VM_Begin();
7006         for (i = 0;i < numsurfaces;i++)
7007         {
7008                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7009                 switch ((int)edict->fields.server->solid)
7010                 {
7011                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7012                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7013                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7014                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7015                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7016                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7017                 }
7018                 color[3] *= r_showbboxes.value;
7019                 color[3] = bound(0, color[3], 1);
7020                 GL_DepthTest(!r_showdisabledepthtest.integer);
7021                 GL_CullFace(r_refdef.view.cullface_front);
7022                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7023         }
7024         SV_VM_End();
7025         prog = prog_save;
7026 }
7027
7028 static void R_DrawEntityBBoxes(void)
7029 {
7030         int i;
7031         prvm_edict_t *edict;
7032         vec3_t center;
7033         prvm_prog_t *prog_save = prog;
7034
7035         // this function draws bounding boxes of server entities
7036         if (!sv.active)
7037                 return;
7038
7039         prog = 0;
7040         SV_VM_Begin();
7041         for (i = 0;i < prog->num_edicts;i++)
7042         {
7043                 edict = PRVM_EDICT_NUM(i);
7044                 if (edict->priv.server->free)
7045                         continue;
7046                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7047                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7048                         continue;
7049                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7050                         continue;
7051                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7052                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7053         }
7054         SV_VM_End();
7055         prog = prog_save;
7056 }
7057
7058 static const int nomodelelement3i[24] =
7059 {
7060         5, 2, 0,
7061         5, 1, 2,
7062         5, 0, 3,
7063         5, 3, 1,
7064         0, 2, 4,
7065         2, 1, 4,
7066         3, 0, 4,
7067         1, 3, 4
7068 };
7069
7070 static const unsigned short nomodelelement3s[24] =
7071 {
7072         5, 2, 0,
7073         5, 1, 2,
7074         5, 0, 3,
7075         5, 3, 1,
7076         0, 2, 4,
7077         2, 1, 4,
7078         3, 0, 4,
7079         1, 3, 4
7080 };
7081
7082 static const float nomodelvertex3f[6*3] =
7083 {
7084         -16,   0,   0,
7085          16,   0,   0,
7086           0, -16,   0,
7087           0,  16,   0,
7088           0,   0, -16,
7089           0,   0,  16
7090 };
7091
7092 static const float nomodelcolor4f[6*4] =
7093 {
7094         0.0f, 0.0f, 0.5f, 1.0f,
7095         0.0f, 0.0f, 0.5f, 1.0f,
7096         0.0f, 0.5f, 0.0f, 1.0f,
7097         0.0f, 0.5f, 0.0f, 1.0f,
7098         0.5f, 0.0f, 0.0f, 1.0f,
7099         0.5f, 0.0f, 0.0f, 1.0f
7100 };
7101
7102 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7103 {
7104         int i;
7105         float f1, f2, *c;
7106         float color4f[6*4];
7107
7108         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);
7109
7110         // this is only called once per entity so numsurfaces is always 1, and
7111         // surfacelist is always {0}, so this code does not handle batches
7112
7113         if (rsurface.ent_flags & RENDER_ADDITIVE)
7114         {
7115                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7116                 GL_DepthMask(false);
7117         }
7118         else if (rsurface.colormod[3] < 1)
7119         {
7120                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7121                 GL_DepthMask(false);
7122         }
7123         else
7124         {
7125                 GL_BlendFunc(GL_ONE, GL_ZERO);
7126                 GL_DepthMask(true);
7127         }
7128         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7129         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7130         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7131         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7132         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7133         for (i = 0, c = color4f;i < 6;i++, c += 4)
7134         {
7135                 c[0] *= rsurface.colormod[0];
7136                 c[1] *= rsurface.colormod[1];
7137                 c[2] *= rsurface.colormod[2];
7138                 c[3] *= rsurface.colormod[3];
7139         }
7140         if (r_refdef.fogenabled)
7141         {
7142                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7143                 {
7144                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7145                         f2 = 1 - f1;
7146                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7147                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7148                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7149                 }
7150         }
7151 //      R_Mesh_ResetTextureState();
7152         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7153         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7154         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7155 }
7156
7157 void R_DrawNoModel(entity_render_t *ent)
7158 {
7159         vec3_t org;
7160         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7161         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7162                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7163         else
7164                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7165 }
7166
7167 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7168 {
7169         vec3_t right1, right2, diff, normal;
7170
7171         VectorSubtract (org2, org1, normal);
7172
7173         // calculate 'right' vector for start
7174         VectorSubtract (r_refdef.view.origin, org1, diff);
7175         CrossProduct (normal, diff, right1);
7176         VectorNormalize (right1);
7177
7178         // calculate 'right' vector for end
7179         VectorSubtract (r_refdef.view.origin, org2, diff);
7180         CrossProduct (normal, diff, right2);
7181         VectorNormalize (right2);
7182
7183         vert[ 0] = org1[0] + width * right1[0];
7184         vert[ 1] = org1[1] + width * right1[1];
7185         vert[ 2] = org1[2] + width * right1[2];
7186         vert[ 3] = org1[0] - width * right1[0];
7187         vert[ 4] = org1[1] - width * right1[1];
7188         vert[ 5] = org1[2] - width * right1[2];
7189         vert[ 6] = org2[0] - width * right2[0];
7190         vert[ 7] = org2[1] - width * right2[1];
7191         vert[ 8] = org2[2] - width * right2[2];
7192         vert[ 9] = org2[0] + width * right2[0];
7193         vert[10] = org2[1] + width * right2[1];
7194         vert[11] = org2[2] + width * right2[2];
7195 }
7196
7197 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)
7198 {
7199         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7200         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7201         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7202         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7203         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7204         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7205         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7206         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7207         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7208         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7209         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7210         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7211 }
7212
7213 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7214 {
7215         int i;
7216         float *vertex3f;
7217         float v[3];
7218         VectorSet(v, x, y, z);
7219         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7220                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7221                         break;
7222         if (i == mesh->numvertices)
7223         {
7224                 if (mesh->numvertices < mesh->maxvertices)
7225                 {
7226                         VectorCopy(v, vertex3f);
7227                         mesh->numvertices++;
7228                 }
7229                 return mesh->numvertices;
7230         }
7231         else
7232                 return i;
7233 }
7234
7235 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7236 {
7237         int i;
7238         int *e, element[3];
7239         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7240         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7241         e = mesh->element3i + mesh->numtriangles * 3;
7242         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7243         {
7244                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7245                 if (mesh->numtriangles < mesh->maxtriangles)
7246                 {
7247                         *e++ = element[0];
7248                         *e++ = element[1];
7249                         *e++ = element[2];
7250                         mesh->numtriangles++;
7251                 }
7252                 element[1] = element[2];
7253         }
7254 }
7255
7256 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7257 {
7258         int i;
7259         int *e, element[3];
7260         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7261         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7262         e = mesh->element3i + mesh->numtriangles * 3;
7263         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7264         {
7265                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7266                 if (mesh->numtriangles < mesh->maxtriangles)
7267                 {
7268                         *e++ = element[0];
7269                         *e++ = element[1];
7270                         *e++ = element[2];
7271                         mesh->numtriangles++;
7272                 }
7273                 element[1] = element[2];
7274         }
7275 }
7276
7277 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7278 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7279 {
7280         int planenum, planenum2;
7281         int w;
7282         int tempnumpoints;
7283         mplane_t *plane, *plane2;
7284         double maxdist;
7285         double temppoints[2][256*3];
7286         // figure out how large a bounding box we need to properly compute this brush
7287         maxdist = 0;
7288         for (w = 0;w < numplanes;w++)
7289                 maxdist = max(maxdist, fabs(planes[w].dist));
7290         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7291         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7292         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7293         {
7294                 w = 0;
7295                 tempnumpoints = 4;
7296                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7297                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7298                 {
7299                         if (planenum2 == planenum)
7300                                 continue;
7301                         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);
7302                         w = !w;
7303                 }
7304                 if (tempnumpoints < 3)
7305                         continue;
7306                 // generate elements forming a triangle fan for this polygon
7307                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7308         }
7309 }
7310
7311 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)
7312 {
7313         texturelayer_t *layer;
7314         layer = t->currentlayers + t->currentnumlayers++;
7315         layer->type = type;
7316         layer->depthmask = depthmask;
7317         layer->blendfunc1 = blendfunc1;
7318         layer->blendfunc2 = blendfunc2;
7319         layer->texture = texture;
7320         layer->texmatrix = *matrix;
7321         layer->color[0] = r;
7322         layer->color[1] = g;
7323         layer->color[2] = b;
7324         layer->color[3] = a;
7325 }
7326
7327 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7328 {
7329         if(parms[0] == 0 && parms[1] == 0)
7330                 return false;
7331         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7332                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7333                         return false;
7334         return true;
7335 }
7336
7337 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7338 {
7339         double index, f;
7340         index = parms[2] + r_refdef.scene.time * parms[3];
7341         index -= floor(index);
7342         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7343         {
7344         default:
7345         case Q3WAVEFUNC_NONE:
7346         case Q3WAVEFUNC_NOISE:
7347         case Q3WAVEFUNC_COUNT:
7348                 f = 0;
7349                 break;
7350         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7351         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7352         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7353         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7354         case Q3WAVEFUNC_TRIANGLE:
7355                 index *= 4;
7356                 f = index - floor(index);
7357                 if (index < 1)
7358                         f = f;
7359                 else if (index < 2)
7360                         f = 1 - f;
7361                 else if (index < 3)
7362                         f = -f;
7363                 else
7364                         f = -(1 - f);
7365                 break;
7366         }
7367         f = parms[0] + parms[1] * f;
7368         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7369                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7370         return (float) f;
7371 }
7372
7373 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7374 {
7375         int w, h, idx;
7376         float f;
7377         float tcmat[12];
7378         matrix4x4_t matrix, temp;
7379         switch(tcmod->tcmod)
7380         {
7381                 case Q3TCMOD_COUNT:
7382                 case Q3TCMOD_NONE:
7383                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7384                                 matrix = r_waterscrollmatrix;
7385                         else
7386                                 matrix = identitymatrix;
7387                         break;
7388                 case Q3TCMOD_ENTITYTRANSLATE:
7389                         // this is used in Q3 to allow the gamecode to control texcoord
7390                         // scrolling on the entity, which is not supported in darkplaces yet.
7391                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7392                         break;
7393                 case Q3TCMOD_ROTATE:
7394                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7395                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7396                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7397                         break;
7398                 case Q3TCMOD_SCALE:
7399                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7400                         break;
7401                 case Q3TCMOD_SCROLL:
7402                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7403                         break;
7404                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7405                         w = (int) tcmod->parms[0];
7406                         h = (int) tcmod->parms[1];
7407                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7408                         f = f - floor(f);
7409                         idx = (int) floor(f * w * h);
7410                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7411                         break;
7412                 case Q3TCMOD_STRETCH:
7413                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7414                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7415                         break;
7416                 case Q3TCMOD_TRANSFORM:
7417                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7418                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7419                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7420                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7421                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7422                         break;
7423                 case Q3TCMOD_TURBULENT:
7424                         // this is handled in the RSurf_PrepareVertices function
7425                         matrix = identitymatrix;
7426                         break;
7427         }
7428         temp = *texmatrix;
7429         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7430 }
7431
7432 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7433 {
7434         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7435         char name[MAX_QPATH];
7436         skinframe_t *skinframe;
7437         unsigned char pixels[296*194];
7438         strlcpy(cache->name, skinname, sizeof(cache->name));
7439         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7440         if (developer_loading.integer)
7441                 Con_Printf("loading %s\n", name);
7442         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7443         if (!skinframe || !skinframe->base)
7444         {
7445                 unsigned char *f;
7446                 fs_offset_t filesize;
7447                 skinframe = NULL;
7448                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7449                 if (f)
7450                 {
7451                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7452                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7453                         Mem_Free(f);
7454                 }
7455         }
7456         cache->skinframe = skinframe;
7457 }
7458
7459 texture_t *R_GetCurrentTexture(texture_t *t)
7460 {
7461         int i;
7462         const entity_render_t *ent = rsurface.entity;
7463         dp_model_t *model = ent->model;
7464         q3shaderinfo_layer_tcmod_t *tcmod;
7465
7466         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7467                 return t->currentframe;
7468         t->update_lastrenderframe = r_textureframe;
7469         t->update_lastrenderentity = (void *)ent;
7470
7471         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7472                 t->camera_entity = ent->entitynumber;
7473         else
7474                 t->camera_entity = 0;
7475
7476         // switch to an alternate material if this is a q1bsp animated material
7477         {
7478                 texture_t *texture = t;
7479                 int s = rsurface.ent_skinnum;
7480                 if ((unsigned int)s >= (unsigned int)model->numskins)
7481                         s = 0;
7482                 if (model->skinscenes)
7483                 {
7484                         if (model->skinscenes[s].framecount > 1)
7485                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7486                         else
7487                                 s = model->skinscenes[s].firstframe;
7488                 }
7489                 if (s > 0)
7490                         t = t + s * model->num_surfaces;
7491                 if (t->animated)
7492                 {
7493                         // use an alternate animation if the entity's frame is not 0,
7494                         // and only if the texture has an alternate animation
7495                         if (rsurface.ent_alttextures && t->anim_total[1])
7496                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7497                         else
7498                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7499                 }
7500                 texture->currentframe = t;
7501         }
7502
7503         // update currentskinframe to be a qw skin or animation frame
7504         if (rsurface.ent_qwskin >= 0)
7505         {
7506                 i = rsurface.ent_qwskin;
7507                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7508                 {
7509                         r_qwskincache_size = cl.maxclients;
7510                         if (r_qwskincache)
7511                                 Mem_Free(r_qwskincache);
7512                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7513                 }
7514                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7515                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7516                 t->currentskinframe = r_qwskincache[i].skinframe;
7517                 if (t->currentskinframe == NULL)
7518                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7519         }
7520         else if (t->numskinframes >= 2)
7521                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7522         if (t->backgroundnumskinframes >= 2)
7523                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7524
7525         t->currentmaterialflags = t->basematerialflags;
7526         t->currentalpha = rsurface.colormod[3];
7527         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7528                 t->currentalpha *= r_wateralpha.value;
7529         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7530                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7531         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7532                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7533         if (!(rsurface.ent_flags & RENDER_LIGHT))
7534                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7535         else if (FAKELIGHT_ENABLED)
7536         {
7537                 // no modellight if using fakelight for the map
7538         }
7539         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7540         {
7541                 // pick a model lighting mode
7542                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7543                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7544                 else
7545                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7546         }
7547         if (rsurface.ent_flags & RENDER_ADDITIVE)
7548                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7549         else if (t->currentalpha < 1)
7550                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7551         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7552                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7553         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7554                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7555         if (t->backgroundnumskinframes)
7556                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7557         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7558         {
7559                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7560                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7561         }
7562         else
7563                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7564         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7565                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7566
7567         // there is no tcmod
7568         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7569         {
7570                 t->currenttexmatrix = r_waterscrollmatrix;
7571                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7572         }
7573         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7574         {
7575                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7576                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7577         }
7578
7579         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7580                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7581         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7582                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7583
7584         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7585         if (t->currentskinframe->qpixels)
7586                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7587         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7588         if (!t->basetexture)
7589                 t->basetexture = r_texture_notexture;
7590         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7591         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7592         t->nmaptexture = t->currentskinframe->nmap;
7593         if (!t->nmaptexture)
7594                 t->nmaptexture = r_texture_blanknormalmap;
7595         t->glosstexture = r_texture_black;
7596         t->glowtexture = t->currentskinframe->glow;
7597         t->fogtexture = t->currentskinframe->fog;
7598         t->reflectmasktexture = t->currentskinframe->reflect;
7599         if (t->backgroundnumskinframes)
7600         {
7601                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7602                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7603                 t->backgroundglosstexture = r_texture_black;
7604                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7605                 if (!t->backgroundnmaptexture)
7606                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7607         }
7608         else
7609         {
7610                 t->backgroundbasetexture = r_texture_white;
7611                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7612                 t->backgroundglosstexture = r_texture_black;
7613                 t->backgroundglowtexture = NULL;
7614         }
7615         t->specularpower = r_shadow_glossexponent.value;
7616         // TODO: store reference values for these in the texture?
7617         t->specularscale = 0;
7618         if (r_shadow_gloss.integer > 0)
7619         {
7620                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7621                 {
7622                         if (r_shadow_glossintensity.value > 0)
7623                         {
7624                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7625                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7626                                 t->specularscale = r_shadow_glossintensity.value;
7627                         }
7628                 }
7629                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7630                 {
7631                         t->glosstexture = r_texture_white;
7632                         t->backgroundglosstexture = r_texture_white;
7633                         t->specularscale = r_shadow_gloss2intensity.value;
7634                         t->specularpower = r_shadow_gloss2exponent.value;
7635                 }
7636         }
7637         t->specularscale *= t->specularscalemod;
7638         t->specularpower *= t->specularpowermod;
7639
7640         // lightmaps mode looks bad with dlights using actual texturing, so turn
7641         // off the colormap and glossmap, but leave the normalmap on as it still
7642         // accurately represents the shading involved
7643         if (gl_lightmaps.integer)
7644         {
7645                 t->basetexture = r_texture_grey128;
7646                 t->pantstexture = r_texture_black;
7647                 t->shirttexture = r_texture_black;
7648                 t->nmaptexture = r_texture_blanknormalmap;
7649                 t->glosstexture = r_texture_black;
7650                 t->glowtexture = NULL;
7651                 t->fogtexture = NULL;
7652                 t->reflectmasktexture = NULL;
7653                 t->backgroundbasetexture = NULL;
7654                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7655                 t->backgroundglosstexture = r_texture_black;
7656                 t->backgroundglowtexture = NULL;
7657                 t->specularscale = 0;
7658                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7659         }
7660
7661         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7662         VectorClear(t->dlightcolor);
7663         t->currentnumlayers = 0;
7664         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7665         {
7666                 int blendfunc1, blendfunc2;
7667                 qboolean depthmask;
7668                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7669                 {
7670                         blendfunc1 = GL_SRC_ALPHA;
7671                         blendfunc2 = GL_ONE;
7672                 }
7673                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7674                 {
7675                         blendfunc1 = GL_SRC_ALPHA;
7676                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7677                 }
7678                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7679                 {
7680                         blendfunc1 = t->customblendfunc[0];
7681                         blendfunc2 = t->customblendfunc[1];
7682                 }
7683                 else
7684                 {
7685                         blendfunc1 = GL_ONE;
7686                         blendfunc2 = GL_ZERO;
7687                 }
7688                 // don't colormod evilblend textures
7689                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7690                         VectorSet(t->lightmapcolor, 1, 1, 1);
7691                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7692                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7693                 {
7694                         // fullbright is not affected by r_refdef.lightmapintensity
7695                         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]);
7696                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7697                                 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]);
7698                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7699                                 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]);
7700                 }
7701                 else
7702                 {
7703                         vec3_t ambientcolor;
7704                         float colorscale;
7705                         // set the color tint used for lights affecting this surface
7706                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7707                         colorscale = 2;
7708                         // q3bsp has no lightmap updates, so the lightstylevalue that
7709                         // would normally be baked into the lightmap must be
7710                         // applied to the color
7711                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7712                         if (model->type == mod_brushq3)
7713                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7714                         colorscale *= r_refdef.lightmapintensity;
7715                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7716                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7717                         // basic lit geometry
7718                         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]);
7719                         // add pants/shirt if needed
7720                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7721                                 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]);
7722                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7723                                 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]);
7724                         // now add ambient passes if needed
7725                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7726                         {
7727                                 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]);
7728                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7729                                         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]);
7730                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7731                                         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]);
7732                         }
7733                 }
7734                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7735                         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]);
7736                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7737                 {
7738                         // if this is opaque use alpha blend which will darken the earlier
7739                         // passes cheaply.
7740                         //
7741                         // if this is an alpha blended material, all the earlier passes
7742                         // were darkened by fog already, so we only need to add the fog
7743                         // color ontop through the fog mask texture
7744                         //
7745                         // if this is an additive blended material, all the earlier passes
7746                         // were darkened by fog already, and we should not add fog color
7747                         // (because the background was not darkened, there is no fog color
7748                         // that was lost behind it).
7749                         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]);
7750                 }
7751         }
7752
7753         return t->currentframe;
7754 }
7755
7756 rsurfacestate_t rsurface;
7757
7758 void RSurf_ActiveWorldEntity(void)
7759 {
7760         dp_model_t *model = r_refdef.scene.worldmodel;
7761         //if (rsurface.entity == r_refdef.scene.worldentity)
7762         //      return;
7763         rsurface.entity = r_refdef.scene.worldentity;
7764         rsurface.skeleton = NULL;
7765         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7766         rsurface.ent_skinnum = 0;
7767         rsurface.ent_qwskin = -1;
7768         rsurface.ent_shadertime = 0;
7769         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7770         rsurface.matrix = identitymatrix;
7771         rsurface.inversematrix = identitymatrix;
7772         rsurface.matrixscale = 1;
7773         rsurface.inversematrixscale = 1;
7774         R_EntityMatrix(&identitymatrix);
7775         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7776         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7777         rsurface.fograngerecip = r_refdef.fograngerecip;
7778         rsurface.fogheightfade = r_refdef.fogheightfade;
7779         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7780         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7781         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7782         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7783         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7784         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7785         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7786         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7787         rsurface.colormod[3] = 1;
7788         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);
7789         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7790         rsurface.frameblend[0].lerp = 1;
7791         rsurface.ent_alttextures = false;
7792         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7793         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7794         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7795         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7796         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7797         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7798         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7799         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7800         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7801         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7802         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7803         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7804         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7805         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7806         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7807         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7808         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7809         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7810         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7811         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7812         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7813         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7814         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7815         rsurface.modelelement3i = model->surfmesh.data_element3i;
7816         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7817         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7818         rsurface.modelelement3s = model->surfmesh.data_element3s;
7819         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7820         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7821         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7822         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7823         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7824         rsurface.modelsurfaces = model->data_surfaces;
7825         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7826         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7827         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7828         rsurface.modelgeneratedvertex = false;
7829         rsurface.batchgeneratedvertex = false;
7830         rsurface.batchfirstvertex = 0;
7831         rsurface.batchnumvertices = 0;
7832         rsurface.batchfirsttriangle = 0;
7833         rsurface.batchnumtriangles = 0;
7834         rsurface.batchvertex3f  = NULL;
7835         rsurface.batchvertex3f_vertexbuffer = NULL;
7836         rsurface.batchvertex3f_bufferoffset = 0;
7837         rsurface.batchsvector3f = NULL;
7838         rsurface.batchsvector3f_vertexbuffer = NULL;
7839         rsurface.batchsvector3f_bufferoffset = 0;
7840         rsurface.batchtvector3f = NULL;
7841         rsurface.batchtvector3f_vertexbuffer = NULL;
7842         rsurface.batchtvector3f_bufferoffset = 0;
7843         rsurface.batchnormal3f  = NULL;
7844         rsurface.batchnormal3f_vertexbuffer = NULL;
7845         rsurface.batchnormal3f_bufferoffset = 0;
7846         rsurface.batchlightmapcolor4f = NULL;
7847         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7848         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7849         rsurface.batchtexcoordtexture2f = NULL;
7850         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7851         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7852         rsurface.batchtexcoordlightmap2f = NULL;
7853         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7854         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7855         rsurface.batchvertexmesh = NULL;
7856         rsurface.batchvertexmeshbuffer = NULL;
7857         rsurface.batchvertex3fbuffer = NULL;
7858         rsurface.batchelement3i = NULL;
7859         rsurface.batchelement3i_indexbuffer = NULL;
7860         rsurface.batchelement3i_bufferoffset = 0;
7861         rsurface.batchelement3s = NULL;
7862         rsurface.batchelement3s_indexbuffer = NULL;
7863         rsurface.batchelement3s_bufferoffset = 0;
7864         rsurface.passcolor4f = NULL;
7865         rsurface.passcolor4f_vertexbuffer = NULL;
7866         rsurface.passcolor4f_bufferoffset = 0;
7867 }
7868
7869 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7870 {
7871         dp_model_t *model = ent->model;
7872         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7873         //      return;
7874         rsurface.entity = (entity_render_t *)ent;
7875         rsurface.skeleton = ent->skeleton;
7876         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7877         rsurface.ent_skinnum = ent->skinnum;
7878         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;
7879         rsurface.ent_shadertime = ent->shadertime;
7880         rsurface.ent_flags = ent->flags;
7881         rsurface.matrix = ent->matrix;
7882         rsurface.inversematrix = ent->inversematrix;
7883         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7884         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7885         R_EntityMatrix(&rsurface.matrix);
7886         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7887         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7888         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7889         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7890         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7891         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7892         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7893         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7894         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7895         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7896         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7897         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7898         rsurface.colormod[3] = ent->alpha;
7899         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7900         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7901         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7902         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7903         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7904         if (ent->model->brush.submodel && !prepass)
7905         {
7906                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7907                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7908         }
7909         if (model->surfmesh.isanimated && model->AnimateVertices)
7910         {
7911                 if (ent->animcache_vertex3f)
7912                 {
7913                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7914                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7915                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7916                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7917                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7918                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7919                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7920                 }
7921                 else if (wanttangents)
7922                 {
7923                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7924                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7925                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7926                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7927                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7928                         rsurface.modelvertexmesh = NULL;
7929                         rsurface.modelvertexmeshbuffer = NULL;
7930                         rsurface.modelvertex3fbuffer = NULL;
7931                 }
7932                 else if (wantnormals)
7933                 {
7934                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7935                         rsurface.modelsvector3f = NULL;
7936                         rsurface.modeltvector3f = NULL;
7937                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7938                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7939                         rsurface.modelvertexmesh = NULL;
7940                         rsurface.modelvertexmeshbuffer = NULL;
7941                         rsurface.modelvertex3fbuffer = NULL;
7942                 }
7943                 else
7944                 {
7945                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7946                         rsurface.modelsvector3f = NULL;
7947                         rsurface.modeltvector3f = NULL;
7948                         rsurface.modelnormal3f = NULL;
7949                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7950                         rsurface.modelvertexmesh = NULL;
7951                         rsurface.modelvertexmeshbuffer = NULL;
7952                         rsurface.modelvertex3fbuffer = NULL;
7953                 }
7954                 rsurface.modelvertex3f_vertexbuffer = 0;
7955                 rsurface.modelvertex3f_bufferoffset = 0;
7956                 rsurface.modelsvector3f_vertexbuffer = 0;
7957                 rsurface.modelsvector3f_bufferoffset = 0;
7958                 rsurface.modeltvector3f_vertexbuffer = 0;
7959                 rsurface.modeltvector3f_bufferoffset = 0;
7960                 rsurface.modelnormal3f_vertexbuffer = 0;
7961                 rsurface.modelnormal3f_bufferoffset = 0;
7962                 rsurface.modelgeneratedvertex = true;
7963         }
7964         else
7965         {
7966                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7967                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7968                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7969                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7970                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7971                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7972                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7973                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7974                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7975                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7976                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7977                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7978                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7979                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7980                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7981                 rsurface.modelgeneratedvertex = false;
7982         }
7983         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7984         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7985         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7986         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7987         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7988         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7989         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7990         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7991         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7992         rsurface.modelelement3i = model->surfmesh.data_element3i;
7993         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7994         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7995         rsurface.modelelement3s = model->surfmesh.data_element3s;
7996         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7997         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7998         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7999         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8000         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8001         rsurface.modelsurfaces = model->data_surfaces;
8002         rsurface.batchgeneratedvertex = false;
8003         rsurface.batchfirstvertex = 0;
8004         rsurface.batchnumvertices = 0;
8005         rsurface.batchfirsttriangle = 0;
8006         rsurface.batchnumtriangles = 0;
8007         rsurface.batchvertex3f  = NULL;
8008         rsurface.batchvertex3f_vertexbuffer = NULL;
8009         rsurface.batchvertex3f_bufferoffset = 0;
8010         rsurface.batchsvector3f = NULL;
8011         rsurface.batchsvector3f_vertexbuffer = NULL;
8012         rsurface.batchsvector3f_bufferoffset = 0;
8013         rsurface.batchtvector3f = NULL;
8014         rsurface.batchtvector3f_vertexbuffer = NULL;
8015         rsurface.batchtvector3f_bufferoffset = 0;
8016         rsurface.batchnormal3f  = NULL;
8017         rsurface.batchnormal3f_vertexbuffer = NULL;
8018         rsurface.batchnormal3f_bufferoffset = 0;
8019         rsurface.batchlightmapcolor4f = NULL;
8020         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8021         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8022         rsurface.batchtexcoordtexture2f = NULL;
8023         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8024         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8025         rsurface.batchtexcoordlightmap2f = NULL;
8026         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8027         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8028         rsurface.batchvertexmesh = NULL;
8029         rsurface.batchvertexmeshbuffer = NULL;
8030         rsurface.batchvertex3fbuffer = NULL;
8031         rsurface.batchelement3i = NULL;
8032         rsurface.batchelement3i_indexbuffer = NULL;
8033         rsurface.batchelement3i_bufferoffset = 0;
8034         rsurface.batchelement3s = NULL;
8035         rsurface.batchelement3s_indexbuffer = NULL;
8036         rsurface.batchelement3s_bufferoffset = 0;
8037         rsurface.passcolor4f = NULL;
8038         rsurface.passcolor4f_vertexbuffer = NULL;
8039         rsurface.passcolor4f_bufferoffset = 0;
8040 }
8041
8042 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)
8043 {
8044         rsurface.entity = r_refdef.scene.worldentity;
8045         rsurface.skeleton = NULL;
8046         rsurface.ent_skinnum = 0;
8047         rsurface.ent_qwskin = -1;
8048         rsurface.ent_shadertime = shadertime;
8049         rsurface.ent_flags = entflags;
8050         rsurface.modelnumvertices = numvertices;
8051         rsurface.modelnumtriangles = numtriangles;
8052         rsurface.matrix = *matrix;
8053         rsurface.inversematrix = *inversematrix;
8054         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8055         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8056         R_EntityMatrix(&rsurface.matrix);
8057         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8058         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8059         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8060         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8061         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8062         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8063         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8064         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8065         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8066         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8067         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8068         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8069         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);
8070         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8071         rsurface.frameblend[0].lerp = 1;
8072         rsurface.ent_alttextures = false;
8073         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8074         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8075         if (wanttangents)
8076         {
8077                 rsurface.modelvertex3f = (float *)vertex3f;
8078                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8079                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8080                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8081         }
8082         else if (wantnormals)
8083         {
8084                 rsurface.modelvertex3f = (float *)vertex3f;
8085                 rsurface.modelsvector3f = NULL;
8086                 rsurface.modeltvector3f = NULL;
8087                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8088         }
8089         else
8090         {
8091                 rsurface.modelvertex3f = (float *)vertex3f;
8092                 rsurface.modelsvector3f = NULL;
8093                 rsurface.modeltvector3f = NULL;
8094                 rsurface.modelnormal3f = NULL;
8095         }
8096         rsurface.modelvertexmesh = NULL;
8097         rsurface.modelvertexmeshbuffer = NULL;
8098         rsurface.modelvertex3fbuffer = NULL;
8099         rsurface.modelvertex3f_vertexbuffer = 0;
8100         rsurface.modelvertex3f_bufferoffset = 0;
8101         rsurface.modelsvector3f_vertexbuffer = 0;
8102         rsurface.modelsvector3f_bufferoffset = 0;
8103         rsurface.modeltvector3f_vertexbuffer = 0;
8104         rsurface.modeltvector3f_bufferoffset = 0;
8105         rsurface.modelnormal3f_vertexbuffer = 0;
8106         rsurface.modelnormal3f_bufferoffset = 0;
8107         rsurface.modelgeneratedvertex = true;
8108         rsurface.modellightmapcolor4f  = (float *)color4f;
8109         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8110         rsurface.modellightmapcolor4f_bufferoffset = 0;
8111         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8112         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8113         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8114         rsurface.modeltexcoordlightmap2f  = NULL;
8115         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8116         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8117         rsurface.modelelement3i = (int *)element3i;
8118         rsurface.modelelement3i_indexbuffer = NULL;
8119         rsurface.modelelement3i_bufferoffset = 0;
8120         rsurface.modelelement3s = (unsigned short *)element3s;
8121         rsurface.modelelement3s_indexbuffer = NULL;
8122         rsurface.modelelement3s_bufferoffset = 0;
8123         rsurface.modellightmapoffsets = NULL;
8124         rsurface.modelsurfaces = NULL;
8125         rsurface.batchgeneratedvertex = false;
8126         rsurface.batchfirstvertex = 0;
8127         rsurface.batchnumvertices = 0;
8128         rsurface.batchfirsttriangle = 0;
8129         rsurface.batchnumtriangles = 0;
8130         rsurface.batchvertex3f  = NULL;
8131         rsurface.batchvertex3f_vertexbuffer = NULL;
8132         rsurface.batchvertex3f_bufferoffset = 0;
8133         rsurface.batchsvector3f = NULL;
8134         rsurface.batchsvector3f_vertexbuffer = NULL;
8135         rsurface.batchsvector3f_bufferoffset = 0;
8136         rsurface.batchtvector3f = NULL;
8137         rsurface.batchtvector3f_vertexbuffer = NULL;
8138         rsurface.batchtvector3f_bufferoffset = 0;
8139         rsurface.batchnormal3f  = NULL;
8140         rsurface.batchnormal3f_vertexbuffer = NULL;
8141         rsurface.batchnormal3f_bufferoffset = 0;
8142         rsurface.batchlightmapcolor4f = NULL;
8143         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8144         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8145         rsurface.batchtexcoordtexture2f = NULL;
8146         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8147         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8148         rsurface.batchtexcoordlightmap2f = NULL;
8149         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8150         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8151         rsurface.batchvertexmesh = NULL;
8152         rsurface.batchvertexmeshbuffer = NULL;
8153         rsurface.batchvertex3fbuffer = NULL;
8154         rsurface.batchelement3i = NULL;
8155         rsurface.batchelement3i_indexbuffer = NULL;
8156         rsurface.batchelement3i_bufferoffset = 0;
8157         rsurface.batchelement3s = NULL;
8158         rsurface.batchelement3s_indexbuffer = NULL;
8159         rsurface.batchelement3s_bufferoffset = 0;
8160         rsurface.passcolor4f = NULL;
8161         rsurface.passcolor4f_vertexbuffer = NULL;
8162         rsurface.passcolor4f_bufferoffset = 0;
8163
8164         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8165         {
8166                 if ((wantnormals || wanttangents) && !normal3f)
8167                 {
8168                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8169                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8170                 }
8171                 if (wanttangents && !svector3f)
8172                 {
8173                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8174                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8175                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8176                 }
8177         }
8178 }
8179
8180 float RSurf_FogPoint(const float *v)
8181 {
8182         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8183         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8184         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8185         float FogHeightFade = r_refdef.fogheightfade;
8186         float fogfrac;
8187         unsigned int fogmasktableindex;
8188         if (r_refdef.fogplaneviewabove)
8189                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8190         else
8191                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8192         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8193         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8194 }
8195
8196 float RSurf_FogVertex(const float *v)
8197 {
8198         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8199         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8200         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8201         float FogHeightFade = rsurface.fogheightfade;
8202         float fogfrac;
8203         unsigned int fogmasktableindex;
8204         if (r_refdef.fogplaneviewabove)
8205                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8206         else
8207                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8208         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8209         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8210 }
8211
8212 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8213 {
8214         int i;
8215         for (i = 0;i < numelements;i++)
8216                 outelement3i[i] = inelement3i[i] + adjust;
8217 }
8218
8219 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8220 extern cvar_t gl_vbo;
8221 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8222 {
8223         int deformindex;
8224         int firsttriangle;
8225         int numtriangles;
8226         int firstvertex;
8227         int endvertex;
8228         int numvertices;
8229         int surfacefirsttriangle;
8230         int surfacenumtriangles;
8231         int surfacefirstvertex;
8232         int surfaceendvertex;
8233         int surfacenumvertices;
8234         int batchnumvertices;
8235         int batchnumtriangles;
8236         int needsupdate;
8237         int i, j;
8238         qboolean gaps;
8239         qboolean dynamicvertex;
8240         float amplitude;
8241         float animpos;
8242         float scale;
8243         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8244         float waveparms[4];
8245         q3shaderinfo_deform_t *deform;
8246         const msurface_t *surface, *firstsurface;
8247         r_vertexmesh_t *vertexmesh;
8248         if (!texturenumsurfaces)
8249                 return;
8250         // find vertex range of this surface batch
8251         gaps = false;
8252         firstsurface = texturesurfacelist[0];
8253         firsttriangle = firstsurface->num_firsttriangle;
8254         batchnumvertices = 0;
8255         batchnumtriangles = 0;
8256         firstvertex = endvertex = firstsurface->num_firstvertex;
8257         for (i = 0;i < texturenumsurfaces;i++)
8258         {
8259                 surface = texturesurfacelist[i];
8260                 if (surface != firstsurface + i)
8261                         gaps = true;
8262                 surfacefirstvertex = surface->num_firstvertex;
8263                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8264                 surfacenumvertices = surface->num_vertices;
8265                 surfacenumtriangles = surface->num_triangles;
8266                 if (firstvertex > surfacefirstvertex)
8267                         firstvertex = surfacefirstvertex;
8268                 if (endvertex < surfaceendvertex)
8269                         endvertex = surfaceendvertex;
8270                 batchnumvertices += surfacenumvertices;
8271                 batchnumtriangles += surfacenumtriangles;
8272         }
8273
8274         // we now know the vertex range used, and if there are any gaps in it
8275         rsurface.batchfirstvertex = firstvertex;
8276         rsurface.batchnumvertices = endvertex - firstvertex;
8277         rsurface.batchfirsttriangle = firsttriangle;
8278         rsurface.batchnumtriangles = batchnumtriangles;
8279
8280         // this variable holds flags for which properties have been updated that
8281         // may require regenerating vertexmesh array...
8282         needsupdate = 0;
8283
8284         // check if any dynamic vertex processing must occur
8285         dynamicvertex = false;
8286
8287         // if there is a chance of animated vertex colors, it's a dynamic batch
8288         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8289         {
8290                 dynamicvertex = true;
8291                 batchneed |= BATCHNEED_NOGAPS;
8292                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8293         }
8294
8295         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8296         {
8297                 switch (deform->deform)
8298                 {
8299                 default:
8300                 case Q3DEFORM_PROJECTIONSHADOW:
8301                 case Q3DEFORM_TEXT0:
8302                 case Q3DEFORM_TEXT1:
8303                 case Q3DEFORM_TEXT2:
8304                 case Q3DEFORM_TEXT3:
8305                 case Q3DEFORM_TEXT4:
8306                 case Q3DEFORM_TEXT5:
8307                 case Q3DEFORM_TEXT6:
8308                 case Q3DEFORM_TEXT7:
8309                 case Q3DEFORM_NONE:
8310                         break;
8311                 case Q3DEFORM_AUTOSPRITE:
8312                         dynamicvertex = true;
8313                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8314                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8315                         break;
8316                 case Q3DEFORM_AUTOSPRITE2:
8317                         dynamicvertex = true;
8318                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8319                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8320                         break;
8321                 case Q3DEFORM_NORMAL:
8322                         dynamicvertex = true;
8323                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8324                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8325                         break;
8326                 case Q3DEFORM_WAVE:
8327                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8328                                 break; // if wavefunc is a nop, ignore this transform
8329                         dynamicvertex = true;
8330                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8331                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8332                         break;
8333                 case Q3DEFORM_BULGE:
8334                         dynamicvertex = true;
8335                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8336                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8337                         break;
8338                 case Q3DEFORM_MOVE:
8339                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8340                                 break; // if wavefunc is a nop, ignore this transform
8341                         dynamicvertex = true;
8342                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8343                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8344                         break;
8345                 }
8346         }
8347         switch(rsurface.texture->tcgen.tcgen)
8348         {
8349         default:
8350         case Q3TCGEN_TEXTURE:
8351                 break;
8352         case Q3TCGEN_LIGHTMAP:
8353                 dynamicvertex = true;
8354                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8355                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8356                 break;
8357         case Q3TCGEN_VECTOR:
8358                 dynamicvertex = true;
8359                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8360                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8361                 break;
8362         case Q3TCGEN_ENVIRONMENT:
8363                 dynamicvertex = true;
8364                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8365                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8366                 break;
8367         }
8368         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8369         {
8370                 dynamicvertex = true;
8371                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8372                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8373         }
8374
8375         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8376         {
8377                 dynamicvertex = true;
8378                 batchneed |= BATCHNEED_NOGAPS;
8379                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8380         }
8381
8382         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8383         {
8384                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8385                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8386                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8387                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8388                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8389                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8390                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8391         }
8392
8393         // when the model data has no vertex buffer (dynamic mesh), we need to
8394         // eliminate gaps
8395         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8396                 batchneed |= BATCHNEED_NOGAPS;
8397
8398         // if needsupdate, we have to do a dynamic vertex batch for sure
8399         if (needsupdate & batchneed)
8400                 dynamicvertex = true;
8401
8402         // see if we need to build vertexmesh from arrays
8403         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8404                 dynamicvertex = true;
8405
8406         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8407         // also some drivers strongly dislike firstvertex
8408         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8409                 dynamicvertex = true;
8410
8411         rsurface.batchvertex3f = rsurface.modelvertex3f;
8412         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8413         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8414         rsurface.batchsvector3f = rsurface.modelsvector3f;
8415         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8416         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8417         rsurface.batchtvector3f = rsurface.modeltvector3f;
8418         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8419         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8420         rsurface.batchnormal3f = rsurface.modelnormal3f;
8421         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8422         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8423         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8424         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8425         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8426         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8427         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8428         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8429         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8430         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8431         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8432         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8433         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8434         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8435         rsurface.batchelement3i = rsurface.modelelement3i;
8436         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8437         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8438         rsurface.batchelement3s = rsurface.modelelement3s;
8439         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8440         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8441
8442         // if any dynamic vertex processing has to occur in software, we copy the
8443         // entire surface list together before processing to rebase the vertices
8444         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8445         //
8446         // if any gaps exist and we do not have a static vertex buffer, we have to
8447         // copy the surface list together to avoid wasting upload bandwidth on the
8448         // vertices in the gaps.
8449         //
8450         // if gaps exist and we have a static vertex buffer, we still have to
8451         // combine the index buffer ranges into one dynamic index buffer.
8452         //
8453         // in all cases we end up with data that can be drawn in one call.
8454
8455         if (!dynamicvertex)
8456         {
8457                 // static vertex data, just set pointers...
8458                 rsurface.batchgeneratedvertex = false;
8459                 // if there are gaps, we want to build a combined index buffer,
8460                 // otherwise use the original static buffer with an appropriate offset
8461                 if (gaps)
8462                 {
8463                         // build a new triangle elements array for this batch
8464                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8465                         rsurface.batchfirsttriangle = 0;
8466                         numtriangles = 0;
8467                         for (i = 0;i < texturenumsurfaces;i++)
8468                         {
8469                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8470                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8471                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8472                                 numtriangles += surfacenumtriangles;
8473                         }
8474                         rsurface.batchelement3i_indexbuffer = NULL;
8475                         rsurface.batchelement3i_bufferoffset = 0;
8476                         rsurface.batchelement3s = NULL;
8477                         rsurface.batchelement3s_indexbuffer = NULL;
8478                         rsurface.batchelement3s_bufferoffset = 0;
8479                         if (endvertex <= 65536)
8480                         {
8481                                 // make a 16bit (unsigned short) index array if possible
8482                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8483                                 for (i = 0;i < numtriangles*3;i++)
8484                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8485                         }
8486                 }
8487                 return;
8488         }
8489
8490         // something needs software processing, do it for real...
8491         // we only directly handle separate array data in this case and then
8492         // generate interleaved data if needed...
8493         rsurface.batchgeneratedvertex = true;
8494
8495         // now copy the vertex data into a combined array and make an index array
8496         // (this is what Quake3 does all the time)
8497         //if (gaps || rsurface.batchfirstvertex)
8498         {
8499                 rsurface.batchvertex3fbuffer = NULL;
8500                 rsurface.batchvertexmesh = NULL;
8501                 rsurface.batchvertexmeshbuffer = NULL;
8502                 rsurface.batchvertex3f = NULL;
8503                 rsurface.batchvertex3f_vertexbuffer = NULL;
8504                 rsurface.batchvertex3f_bufferoffset = 0;
8505                 rsurface.batchsvector3f = NULL;
8506                 rsurface.batchsvector3f_vertexbuffer = NULL;
8507                 rsurface.batchsvector3f_bufferoffset = 0;
8508                 rsurface.batchtvector3f = NULL;
8509                 rsurface.batchtvector3f_vertexbuffer = NULL;
8510                 rsurface.batchtvector3f_bufferoffset = 0;
8511                 rsurface.batchnormal3f = NULL;
8512                 rsurface.batchnormal3f_vertexbuffer = NULL;
8513                 rsurface.batchnormal3f_bufferoffset = 0;
8514                 rsurface.batchlightmapcolor4f = NULL;
8515                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8516                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8517                 rsurface.batchtexcoordtexture2f = NULL;
8518                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8519                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8520                 rsurface.batchtexcoordlightmap2f = NULL;
8521                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8522                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8523                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8524                 rsurface.batchelement3i_indexbuffer = NULL;
8525                 rsurface.batchelement3i_bufferoffset = 0;
8526                 rsurface.batchelement3s = NULL;
8527                 rsurface.batchelement3s_indexbuffer = NULL;
8528                 rsurface.batchelement3s_bufferoffset = 0;
8529                 // we'll only be setting up certain arrays as needed
8530                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8531                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8532                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8533                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8534                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8535                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8536                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8537                 {
8538                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8539                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8540                 }
8541                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8542                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8543                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8544                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8545                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8546                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8547                 numvertices = 0;
8548                 numtriangles = 0;
8549                 for (i = 0;i < texturenumsurfaces;i++)
8550                 {
8551                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8552                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8553                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8554                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8555                         // copy only the data requested
8556                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8557                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8558                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8559                         {
8560                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8561                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8562                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8563                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8564                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8565                                 {
8566                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8567                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8568                                 }
8569                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8570                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8571                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8572                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8573                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8574                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8575                         }
8576                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8577                         numvertices += surfacenumvertices;
8578                         numtriangles += surfacenumtriangles;
8579                 }
8580
8581                 // generate a 16bit index array as well if possible
8582                 // (in general, dynamic batches fit)
8583                 if (numvertices <= 65536)
8584                 {
8585                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8586                         for (i = 0;i < numtriangles*3;i++)
8587                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8588                 }
8589
8590                 // since we've copied everything, the batch now starts at 0
8591                 rsurface.batchfirstvertex = 0;
8592                 rsurface.batchnumvertices = batchnumvertices;
8593                 rsurface.batchfirsttriangle = 0;
8594                 rsurface.batchnumtriangles = batchnumtriangles;
8595         }
8596
8597         // q1bsp surfaces rendered in vertex color mode have to have colors
8598         // calculated based on lightstyles
8599         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8600         {
8601                 // generate color arrays for the surfaces in this list
8602                 int c[4];
8603                 int scale;
8604                 int size3;
8605                 const int *offsets;
8606                 const unsigned char *lm;
8607                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8608                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8609                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8610                 numvertices = 0;
8611                 for (i = 0;i < texturenumsurfaces;i++)
8612                 {
8613                         surface = texturesurfacelist[i];
8614                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8615                         surfacenumvertices = surface->num_vertices;
8616                         if (surface->lightmapinfo->samples)
8617                         {
8618                                 for (j = 0;j < surfacenumvertices;j++)
8619                                 {
8620                                         lm = surface->lightmapinfo->samples + offsets[j];
8621                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8622                                         VectorScale(lm, scale, c);
8623                                         if (surface->lightmapinfo->styles[1] != 255)
8624                                         {
8625                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8626                                                 lm += size3;
8627                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8628                                                 VectorMA(c, scale, lm, c);
8629                                                 if (surface->lightmapinfo->styles[2] != 255)
8630                                                 {
8631                                                         lm += size3;
8632                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8633                                                         VectorMA(c, scale, lm, c);
8634                                                         if (surface->lightmapinfo->styles[3] != 255)
8635                                                         {
8636                                                                 lm += size3;
8637                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8638                                                                 VectorMA(c, scale, lm, c);
8639                                                         }
8640                                                 }
8641                                         }
8642                                         c[0] >>= 7;
8643                                         c[1] >>= 7;
8644                                         c[2] >>= 7;
8645                                         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);
8646                                         numvertices++;
8647                                 }
8648                         }
8649                         else
8650                         {
8651                                 for (j = 0;j < surfacenumvertices;j++)
8652                                 {
8653                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8654                                         numvertices++;
8655                                 }
8656                         }
8657                 }
8658         }
8659
8660         // if vertices are deformed (sprite flares and things in maps, possibly
8661         // water waves, bulges and other deformations), modify the copied vertices
8662         // in place
8663         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8664         {
8665                 switch (deform->deform)
8666                 {
8667                 default:
8668                 case Q3DEFORM_PROJECTIONSHADOW:
8669                 case Q3DEFORM_TEXT0:
8670                 case Q3DEFORM_TEXT1:
8671                 case Q3DEFORM_TEXT2:
8672                 case Q3DEFORM_TEXT3:
8673                 case Q3DEFORM_TEXT4:
8674                 case Q3DEFORM_TEXT5:
8675                 case Q3DEFORM_TEXT6:
8676                 case Q3DEFORM_TEXT7:
8677                 case Q3DEFORM_NONE:
8678                         break;
8679                 case Q3DEFORM_AUTOSPRITE:
8680                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8681                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8682                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8683                         VectorNormalize(newforward);
8684                         VectorNormalize(newright);
8685                         VectorNormalize(newup);
8686 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8687 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8688 //                      rsurface.batchvertex3f_bufferoffset = 0;
8689 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8690 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8691 //                      rsurface.batchsvector3f_bufferoffset = 0;
8692 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8693 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8694 //                      rsurface.batchtvector3f_bufferoffset = 0;
8695 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8696 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8697 //                      rsurface.batchnormal3f_bufferoffset = 0;
8698                         // a single autosprite surface can contain multiple sprites...
8699                         for (j = 0;j < batchnumvertices - 3;j += 4)
8700                         {
8701                                 VectorClear(center);
8702                                 for (i = 0;i < 4;i++)
8703                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8704                                 VectorScale(center, 0.25f, center);
8705                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8706                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8707                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8708                                 for (i = 0;i < 4;i++)
8709                                 {
8710                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8711                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8712                                 }
8713                         }
8714                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8715                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8716                         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);
8717                         break;
8718                 case Q3DEFORM_AUTOSPRITE2:
8719                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8720                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8721                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8722                         VectorNormalize(newforward);
8723                         VectorNormalize(newright);
8724                         VectorNormalize(newup);
8725 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8726 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8727 //                      rsurface.batchvertex3f_bufferoffset = 0;
8728                         {
8729                                 const float *v1, *v2;
8730                                 vec3_t start, end;
8731                                 float f, l;
8732                                 struct
8733                                 {
8734                                         float length2;
8735                                         const float *v1;
8736                                         const float *v2;
8737                                 }
8738                                 shortest[2];
8739                                 memset(shortest, 0, sizeof(shortest));
8740                                 // a single autosprite surface can contain multiple sprites...
8741                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8742                                 {
8743                                         VectorClear(center);
8744                                         for (i = 0;i < 4;i++)
8745                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8746                                         VectorScale(center, 0.25f, center);
8747                                         // find the two shortest edges, then use them to define the
8748                                         // axis vectors for rotating around the central axis
8749                                         for (i = 0;i < 6;i++)
8750                                         {
8751                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8752                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8753                                                 l = VectorDistance2(v1, v2);
8754                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8755                                                 if (v1[2] != v2[2])
8756                                                         l += (1.0f / 1024.0f);
8757                                                 if (shortest[0].length2 > l || i == 0)
8758                                                 {
8759                                                         shortest[1] = shortest[0];
8760                                                         shortest[0].length2 = l;
8761                                                         shortest[0].v1 = v1;
8762                                                         shortest[0].v2 = v2;
8763                                                 }
8764                                                 else if (shortest[1].length2 > l || i == 1)
8765                                                 {
8766                                                         shortest[1].length2 = l;
8767                                                         shortest[1].v1 = v1;
8768                                                         shortest[1].v2 = v2;
8769                                                 }
8770                                         }
8771                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8772                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8773                                         // this calculates the right vector from the shortest edge
8774                                         // and the up vector from the edge midpoints
8775                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8776                                         VectorNormalize(right);
8777                                         VectorSubtract(end, start, up);
8778                                         VectorNormalize(up);
8779                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8780                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8781                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8782                                         VectorNegate(forward, forward);
8783                                         VectorReflect(forward, 0, up, forward);
8784                                         VectorNormalize(forward);
8785                                         CrossProduct(up, forward, newright);
8786                                         VectorNormalize(newright);
8787                                         // rotate the quad around the up axis vector, this is made
8788                                         // especially easy by the fact we know the quad is flat,
8789                                         // so we only have to subtract the center position and
8790                                         // measure distance along the right vector, and then
8791                                         // multiply that by the newright vector and add back the
8792                                         // center position
8793                                         // we also need to subtract the old position to undo the
8794                                         // displacement from the center, which we do with a
8795                                         // DotProduct, the subtraction/addition of center is also
8796                                         // optimized into DotProducts here
8797                                         l = DotProduct(right, center);
8798                                         for (i = 0;i < 4;i++)
8799                                         {
8800                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8801                                                 f = DotProduct(right, v1) - l;
8802                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8803                                         }
8804                                 }
8805                         }
8806                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8807                         {
8808 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8809 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8810 //                              rsurface.batchnormal3f_bufferoffset = 0;
8811                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8812                         }
8813                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8814                         {
8815 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8816 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8817 //                              rsurface.batchsvector3f_bufferoffset = 0;
8818 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8819 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8820 //                              rsurface.batchtvector3f_bufferoffset = 0;
8821                                 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);
8822                         }
8823                         break;
8824                 case Q3DEFORM_NORMAL:
8825                         // deform the normals to make reflections wavey
8826                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8827                         rsurface.batchnormal3f_vertexbuffer = NULL;
8828                         rsurface.batchnormal3f_bufferoffset = 0;
8829                         for (j = 0;j < batchnumvertices;j++)
8830                         {
8831                                 float vertex[3];
8832                                 float *normal = rsurface.batchnormal3f + 3*j;
8833                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8834                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8835                                 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]);
8836                                 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]);
8837                                 VectorNormalize(normal);
8838                         }
8839                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8840                         {
8841 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8842 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8843 //                              rsurface.batchsvector3f_bufferoffset = 0;
8844 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8845 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8846 //                              rsurface.batchtvector3f_bufferoffset = 0;
8847                                 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);
8848                         }
8849                         break;
8850                 case Q3DEFORM_WAVE:
8851                         // deform vertex array to make wavey water and flags and such
8852                         waveparms[0] = deform->waveparms[0];
8853                         waveparms[1] = deform->waveparms[1];
8854                         waveparms[2] = deform->waveparms[2];
8855                         waveparms[3] = deform->waveparms[3];
8856                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8857                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8858                         // this is how a divisor of vertex influence on deformation
8859                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8860                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8861 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8862 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8863 //                      rsurface.batchvertex3f_bufferoffset = 0;
8864 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8865 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8866 //                      rsurface.batchnormal3f_bufferoffset = 0;
8867                         for (j = 0;j < batchnumvertices;j++)
8868                         {
8869                                 // if the wavefunc depends on time, evaluate it per-vertex
8870                                 if (waveparms[3])
8871                                 {
8872                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8873                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8874                                 }
8875                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8876                         }
8877                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8878                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8879                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8880                         {
8881 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8882 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8883 //                              rsurface.batchsvector3f_bufferoffset = 0;
8884 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8885 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8886 //                              rsurface.batchtvector3f_bufferoffset = 0;
8887                                 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);
8888                         }
8889                         break;
8890                 case Q3DEFORM_BULGE:
8891                         // deform vertex array to make the surface have moving bulges
8892 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8893 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8894 //                      rsurface.batchvertex3f_bufferoffset = 0;
8895 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8896 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8897 //                      rsurface.batchnormal3f_bufferoffset = 0;
8898                         for (j = 0;j < batchnumvertices;j++)
8899                         {
8900                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8901                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8902                         }
8903                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8904                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8905                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8906                         {
8907 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8908 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8909 //                              rsurface.batchsvector3f_bufferoffset = 0;
8910 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8911 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8912 //                              rsurface.batchtvector3f_bufferoffset = 0;
8913                                 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);
8914                         }
8915                         break;
8916                 case Q3DEFORM_MOVE:
8917                         // deform vertex array
8918                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8919                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8920                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8921                         VectorScale(deform->parms, scale, waveparms);
8922 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8923 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8924 //                      rsurface.batchvertex3f_bufferoffset = 0;
8925                         for (j = 0;j < batchnumvertices;j++)
8926                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8927                         break;
8928                 }
8929         }
8930
8931         // generate texcoords based on the chosen texcoord source
8932         switch(rsurface.texture->tcgen.tcgen)
8933         {
8934         default:
8935         case Q3TCGEN_TEXTURE:
8936                 break;
8937         case Q3TCGEN_LIGHTMAP:
8938 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8939 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8940 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8941                 if (rsurface.batchtexcoordlightmap2f)
8942                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8943                 break;
8944         case Q3TCGEN_VECTOR:
8945 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8946 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8947 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8948                 for (j = 0;j < batchnumvertices;j++)
8949                 {
8950                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8951                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8952                 }
8953                 break;
8954         case Q3TCGEN_ENVIRONMENT:
8955                 // make environment reflections using a spheremap
8956                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8957                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8958                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8959                 for (j = 0;j < batchnumvertices;j++)
8960                 {
8961                         // identical to Q3A's method, but executed in worldspace so
8962                         // carried models can be shiny too
8963
8964                         float viewer[3], d, reflected[3], worldreflected[3];
8965
8966                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8967                         // VectorNormalize(viewer);
8968
8969                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8970
8971                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8972                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8973                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8974                         // note: this is proportinal to viewer, so we can normalize later
8975
8976                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8977                         VectorNormalize(worldreflected);
8978
8979                         // note: this sphere map only uses world x and z!
8980                         // so positive and negative y will LOOK THE SAME.
8981                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8982                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8983                 }
8984                 break;
8985         }
8986         // the only tcmod that needs software vertex processing is turbulent, so
8987         // check for it here and apply the changes if needed
8988         // and we only support that as the first one
8989         // (handling a mixture of turbulent and other tcmods would be problematic
8990         //  without punting it entirely to a software path)
8991         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8992         {
8993                 amplitude = rsurface.texture->tcmods[0].parms[1];
8994                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8995 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8996 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8997 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8998                 for (j = 0;j < batchnumvertices;j++)
8999                 {
9000                         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);
9001                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9002                 }
9003         }
9004
9005         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9006         {
9007                 // convert the modified arrays to vertex structs
9008 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9009 //              rsurface.batchvertexmeshbuffer = NULL;
9010                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9011                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9012                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9013                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9014                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9015                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9016                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9017                 {
9018                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9019                         {
9020                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9021                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9022                         }
9023                 }
9024                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9025                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9026                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9027                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9028                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9029                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9030                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9031                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9032                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9033         }
9034 }
9035
9036 void RSurf_DrawBatch(void)
9037 {
9038         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9039         // through the pipeline, killing it earlier in the pipeline would have
9040         // per-surface overhead rather than per-batch overhead, so it's best to
9041         // reject it here, before it hits glDraw.
9042         if (rsurface.batchnumtriangles == 0)
9043                 return;
9044 #if 0
9045         // batch debugging code
9046         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9047         {
9048                 int i;
9049                 int j;
9050                 int c;
9051                 const int *e;
9052                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9053                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9054                 {
9055                         c = e[i];
9056                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9057                         {
9058                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9059                                 {
9060                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9061                                                 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);
9062                                         break;
9063                                 }
9064                         }
9065                 }
9066         }
9067 #endif
9068         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);
9069 }
9070
9071 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9072 {
9073         // pick the closest matching water plane
9074         int planeindex, vertexindex, bestplaneindex = -1;
9075         float d, bestd;
9076         vec3_t vert;
9077         const float *v;
9078         r_waterstate_waterplane_t *p;
9079         qboolean prepared = false;
9080         bestd = 0;
9081         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9082         {
9083                 if(p->camera_entity != rsurface.texture->camera_entity)
9084                         continue;
9085                 d = 0;
9086                 if(!prepared)
9087                 {
9088                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9089                         prepared = true;
9090                         if(rsurface.batchnumvertices == 0)
9091                                 break;
9092                 }
9093                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9094                 {
9095                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9096                         d += fabs(PlaneDiff(vert, &p->plane));
9097                 }
9098                 if (bestd > d || bestplaneindex < 0)
9099                 {
9100                         bestd = d;
9101                         bestplaneindex = planeindex;
9102                 }
9103         }
9104         return bestplaneindex;
9105         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9106         // this situation though, as it might be better to render single larger
9107         // batches with useless stuff (backface culled for example) than to
9108         // render multiple smaller batches
9109 }
9110
9111 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9112 {
9113         int i;
9114         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9115         rsurface.passcolor4f_vertexbuffer = 0;
9116         rsurface.passcolor4f_bufferoffset = 0;
9117         for (i = 0;i < rsurface.batchnumvertices;i++)
9118                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9119 }
9120
9121 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9122 {
9123         int i;
9124         float f;
9125         const float *v;
9126         const float *c;
9127         float *c2;
9128         if (rsurface.passcolor4f)
9129         {
9130                 // generate color arrays
9131                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9132                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9133                 rsurface.passcolor4f_vertexbuffer = 0;
9134                 rsurface.passcolor4f_bufferoffset = 0;
9135                 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)
9136                 {
9137                         f = RSurf_FogVertex(v);
9138                         c2[0] = c[0] * f;
9139                         c2[1] = c[1] * f;
9140                         c2[2] = c[2] * f;
9141                         c2[3] = c[3];
9142                 }
9143         }
9144         else
9145         {
9146                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9147                 rsurface.passcolor4f_vertexbuffer = 0;
9148                 rsurface.passcolor4f_bufferoffset = 0;
9149                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9150                 {
9151                         f = RSurf_FogVertex(v);
9152                         c2[0] = f;
9153                         c2[1] = f;
9154                         c2[2] = f;
9155                         c2[3] = 1;
9156                 }
9157         }
9158 }
9159
9160 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9161 {
9162         int i;
9163         float f;
9164         const float *v;
9165         const float *c;
9166         float *c2;
9167         if (!rsurface.passcolor4f)
9168                 return;
9169         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9170         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9171         rsurface.passcolor4f_vertexbuffer = 0;
9172         rsurface.passcolor4f_bufferoffset = 0;
9173         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)
9174         {
9175                 f = RSurf_FogVertex(v);
9176                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9177                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9178                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9179                 c2[3] = c[3];
9180         }
9181 }
9182
9183 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9184 {
9185         int i;
9186         const float *c;
9187         float *c2;
9188         if (!rsurface.passcolor4f)
9189                 return;
9190         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9191         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9192         rsurface.passcolor4f_vertexbuffer = 0;
9193         rsurface.passcolor4f_bufferoffset = 0;
9194         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9195         {
9196                 c2[0] = c[0] * r;
9197                 c2[1] = c[1] * g;
9198                 c2[2] = c[2] * b;
9199                 c2[3] = c[3] * a;
9200         }
9201 }
9202
9203 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9204 {
9205         int i;
9206         const float *c;
9207         float *c2;
9208         if (!rsurface.passcolor4f)
9209                 return;
9210         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9211         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9212         rsurface.passcolor4f_vertexbuffer = 0;
9213         rsurface.passcolor4f_bufferoffset = 0;
9214         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9215         {
9216                 c2[0] = c[0] + r_refdef.scene.ambient;
9217                 c2[1] = c[1] + r_refdef.scene.ambient;
9218                 c2[2] = c[2] + r_refdef.scene.ambient;
9219                 c2[3] = c[3];
9220         }
9221 }
9222
9223 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9224 {
9225         // TODO: optimize
9226         rsurface.passcolor4f = NULL;
9227         rsurface.passcolor4f_vertexbuffer = 0;
9228         rsurface.passcolor4f_bufferoffset = 0;
9229         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9230         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9231         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9232         GL_Color(r, g, b, a);
9233         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9234         RSurf_DrawBatch();
9235 }
9236
9237 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9238 {
9239         // TODO: optimize applyfog && applycolor case
9240         // just apply fog if necessary, and tint the fog color array if necessary
9241         rsurface.passcolor4f = NULL;
9242         rsurface.passcolor4f_vertexbuffer = 0;
9243         rsurface.passcolor4f_bufferoffset = 0;
9244         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9245         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9246         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9247         GL_Color(r, g, b, a);
9248         RSurf_DrawBatch();
9249 }
9250
9251 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9252 {
9253         // TODO: optimize
9254         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9255         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9256         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9257         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9258         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9259         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9260         GL_Color(r, g, b, a);
9261         RSurf_DrawBatch();
9262 }
9263
9264 static void RSurf_DrawBatch_GL11_ClampColor(void)
9265 {
9266         int i;
9267         const float *c1;
9268         float *c2;
9269         if (!rsurface.passcolor4f)
9270                 return;
9271         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9272         {
9273                 c2[0] = bound(0.0f, c1[0], 1.0f);
9274                 c2[1] = bound(0.0f, c1[1], 1.0f);
9275                 c2[2] = bound(0.0f, c1[2], 1.0f);
9276                 c2[3] = bound(0.0f, c1[3], 1.0f);
9277         }
9278 }
9279
9280 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9281 {
9282         int i;
9283         float f;
9284         const float *v;
9285         const float *n;
9286         float *c;
9287         //vec3_t eyedir;
9288
9289         // fake shading
9290         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9291         rsurface.passcolor4f_vertexbuffer = 0;
9292         rsurface.passcolor4f_bufferoffset = 0;
9293         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)
9294         {
9295                 f = -DotProduct(r_refdef.view.forward, n);
9296                 f = max(0, f);
9297                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9298                 f *= r_refdef.lightmapintensity;
9299                 Vector4Set(c, f, f, f, 1);
9300         }
9301 }
9302
9303 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9304 {
9305         RSurf_DrawBatch_GL11_ApplyFakeLight();
9306         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9307         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9308         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9309         GL_Color(r, g, b, a);
9310         RSurf_DrawBatch();
9311 }
9312
9313 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9314 {
9315         int i;
9316         float f;
9317         float alpha;
9318         const float *v;
9319         const float *n;
9320         float *c;
9321         vec3_t ambientcolor;
9322         vec3_t diffusecolor;
9323         vec3_t lightdir;
9324         // TODO: optimize
9325         // model lighting
9326         VectorCopy(rsurface.modellight_lightdir, lightdir);
9327         f = 0.5f * r_refdef.lightmapintensity;
9328         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9329         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9330         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9331         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9332         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9333         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9334         alpha = *a;
9335         if (VectorLength2(diffusecolor) > 0)
9336         {
9337                 // q3-style directional shading
9338                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9339                 rsurface.passcolor4f_vertexbuffer = 0;
9340                 rsurface.passcolor4f_bufferoffset = 0;
9341                 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)
9342                 {
9343                         if ((f = DotProduct(n, lightdir)) > 0)
9344                                 VectorMA(ambientcolor, f, diffusecolor, c);
9345                         else
9346                                 VectorCopy(ambientcolor, c);
9347                         c[3] = alpha;
9348                 }
9349                 *r = 1;
9350                 *g = 1;
9351                 *b = 1;
9352                 *a = 1;
9353                 *applycolor = false;
9354         }
9355         else
9356         {
9357                 *r = ambientcolor[0];
9358                 *g = ambientcolor[1];
9359                 *b = ambientcolor[2];
9360                 rsurface.passcolor4f = NULL;
9361                 rsurface.passcolor4f_vertexbuffer = 0;
9362                 rsurface.passcolor4f_bufferoffset = 0;
9363         }
9364 }
9365
9366 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9367 {
9368         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9369         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9370         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9371         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9372         GL_Color(r, g, b, a);
9373         RSurf_DrawBatch();
9374 }
9375
9376 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9377 {
9378         int i;
9379         float f;
9380         const float *v;
9381         float *c;
9382
9383         // fake shading
9384         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9385         rsurface.passcolor4f_vertexbuffer = 0;
9386         rsurface.passcolor4f_bufferoffset = 0;
9387
9388         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9389         {
9390                 f = 1 - RSurf_FogVertex(v);
9391                 c[0] = r;
9392                 c[1] = g;
9393                 c[2] = b;
9394                 c[3] = f * a;
9395         }
9396 }
9397
9398 void RSurf_SetupDepthAndCulling(void)
9399 {
9400         // submodels are biased to avoid z-fighting with world surfaces that they
9401         // may be exactly overlapping (avoids z-fighting artifacts on certain
9402         // doors and things in Quake maps)
9403         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9404         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9405         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9406         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9407 }
9408
9409 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9410 {
9411         // transparent sky would be ridiculous
9412         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9413                 return;
9414         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9415         skyrenderlater = true;
9416         RSurf_SetupDepthAndCulling();
9417         GL_DepthMask(true);
9418         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9419         // skymasking on them, and Quake3 never did sky masking (unlike
9420         // software Quake and software Quake2), so disable the sky masking
9421         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9422         // and skymasking also looks very bad when noclipping outside the
9423         // level, so don't use it then either.
9424         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9425         {
9426                 R_Mesh_ResetTextureState();
9427                 if (skyrendermasked)
9428                 {
9429                         R_SetupShader_DepthOrShadow();
9430                         // depth-only (masking)
9431                         GL_ColorMask(0,0,0,0);
9432                         // just to make sure that braindead drivers don't draw
9433                         // anything despite that colormask...
9434                         GL_BlendFunc(GL_ZERO, GL_ONE);
9435                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9436                         if (rsurface.batchvertex3fbuffer)
9437                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9438                         else
9439                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9440                 }
9441                 else
9442                 {
9443                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9444                         // fog sky
9445                         GL_BlendFunc(GL_ONE, GL_ZERO);
9446                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9447                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9448                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9449                 }
9450                 RSurf_DrawBatch();
9451                 if (skyrendermasked)
9452                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9453         }
9454         R_Mesh_ResetTextureState();
9455         GL_Color(1, 1, 1, 1);
9456 }
9457
9458 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9459 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9460 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9461 {
9462         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9463                 return;
9464         if (prepass)
9465         {
9466                 // render screenspace normalmap to texture
9467                 GL_DepthMask(true);
9468                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9469                 RSurf_DrawBatch();
9470                 return;
9471         }
9472
9473         // bind lightmap texture
9474
9475         // water/refraction/reflection/camera surfaces have to be handled specially
9476         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9477         {
9478                 int start, end, startplaneindex;
9479                 for (start = 0;start < texturenumsurfaces;start = end)
9480                 {
9481                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9482                         if(startplaneindex < 0)
9483                         {
9484                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9485                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9486                                 end = start + 1;
9487                                 continue;
9488                         }
9489                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9490                                 ;
9491                         // now that we have a batch using the same planeindex, render it
9492                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9493                         {
9494                                 // render water or distortion background
9495                                 GL_DepthMask(true);
9496                                 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));
9497                                 RSurf_DrawBatch();
9498                                 // blend surface on top
9499                                 GL_DepthMask(false);
9500                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9501                                 RSurf_DrawBatch();
9502                         }
9503                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9504                         {
9505                                 // render surface with reflection texture as input
9506                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9507                                 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));
9508                                 RSurf_DrawBatch();
9509                         }
9510                 }
9511                 return;
9512         }
9513
9514         // render surface batch normally
9515         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9516         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9517         RSurf_DrawBatch();
9518 }
9519
9520 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9521 {
9522         // OpenGL 1.3 path - anything not completely ancient
9523         qboolean applycolor;
9524         qboolean applyfog;
9525         int layerindex;
9526         const texturelayer_t *layer;
9527         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);
9528         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9529
9530         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9531         {
9532                 vec4_t layercolor;
9533                 int layertexrgbscale;
9534                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9535                 {
9536                         if (layerindex == 0)
9537                                 GL_AlphaTest(true);
9538                         else
9539                         {
9540                                 GL_AlphaTest(false);
9541                                 GL_DepthFunc(GL_EQUAL);
9542                         }
9543                 }
9544                 GL_DepthMask(layer->depthmask && writedepth);
9545                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9546                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9547                 {
9548                         layertexrgbscale = 4;
9549                         VectorScale(layer->color, 0.25f, layercolor);
9550                 }
9551                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9552                 {
9553                         layertexrgbscale = 2;
9554                         VectorScale(layer->color, 0.5f, layercolor);
9555                 }
9556                 else
9557                 {
9558                         layertexrgbscale = 1;
9559                         VectorScale(layer->color, 1.0f, layercolor);
9560                 }
9561                 layercolor[3] = layer->color[3];
9562                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9563                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9564                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9565                 switch (layer->type)
9566                 {
9567                 case TEXTURELAYERTYPE_LITTEXTURE:
9568                         // single-pass lightmapped texture with 2x rgbscale
9569                         R_Mesh_TexBind(0, r_texture_white);
9570                         R_Mesh_TexMatrix(0, NULL);
9571                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9572                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9573                         R_Mesh_TexBind(1, layer->texture);
9574                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9575                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9576                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9577                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9578                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9579                         else if (FAKELIGHT_ENABLED)
9580                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9581                         else if (rsurface.uselightmaptexture)
9582                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9583                         else
9584                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9585                         break;
9586                 case TEXTURELAYERTYPE_TEXTURE:
9587                         // singletexture unlit texture with transparency support
9588                         R_Mesh_TexBind(0, layer->texture);
9589                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9590                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9591                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9592                         R_Mesh_TexBind(1, 0);
9593                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9594                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9595                         break;
9596                 case TEXTURELAYERTYPE_FOG:
9597                         // singletexture fogging
9598                         if (layer->texture)
9599                         {
9600                                 R_Mesh_TexBind(0, layer->texture);
9601                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9602                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9603                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9604                         }
9605                         else
9606                         {
9607                                 R_Mesh_TexBind(0, 0);
9608                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9609                         }
9610                         R_Mesh_TexBind(1, 0);
9611                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9612                         // generate a color array for the fog pass
9613                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9614                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9615                         RSurf_DrawBatch();
9616                         break;
9617                 default:
9618                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9619                 }
9620         }
9621         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9622         {
9623                 GL_DepthFunc(GL_LEQUAL);
9624                 GL_AlphaTest(false);
9625         }
9626 }
9627
9628 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9629 {
9630         // OpenGL 1.1 - crusty old voodoo path
9631         qboolean applyfog;
9632         int layerindex;
9633         const texturelayer_t *layer;
9634         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);
9635         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9636
9637         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9638         {
9639                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9640                 {
9641                         if (layerindex == 0)
9642                                 GL_AlphaTest(true);
9643                         else
9644                         {
9645                                 GL_AlphaTest(false);
9646                                 GL_DepthFunc(GL_EQUAL);
9647                         }
9648                 }
9649                 GL_DepthMask(layer->depthmask && writedepth);
9650                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9651                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9652                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9653                 switch (layer->type)
9654                 {
9655                 case TEXTURELAYERTYPE_LITTEXTURE:
9656                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9657                         {
9658                                 // two-pass lit texture with 2x rgbscale
9659                                 // first the lightmap pass
9660                                 R_Mesh_TexBind(0, r_texture_white);
9661                                 R_Mesh_TexMatrix(0, NULL);
9662                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9663                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9664                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9665                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9666                                 else if (FAKELIGHT_ENABLED)
9667                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9668                                 else if (rsurface.uselightmaptexture)
9669                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9670                                 else
9671                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9672                                 // then apply the texture to it
9673                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9674                                 R_Mesh_TexBind(0, layer->texture);
9675                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9676                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9677                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9678                                 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);
9679                         }
9680                         else
9681                         {
9682                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9683                                 R_Mesh_TexBind(0, layer->texture);
9684                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9685                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9686                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9687                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9688                                         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);
9689                                 else
9690                                         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);
9691                         }
9692                         break;
9693                 case TEXTURELAYERTYPE_TEXTURE:
9694                         // singletexture unlit texture with transparency support
9695                         R_Mesh_TexBind(0, layer->texture);
9696                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9697                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9698                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9699                         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);
9700                         break;
9701                 case TEXTURELAYERTYPE_FOG:
9702                         // singletexture fogging
9703                         if (layer->texture)
9704                         {
9705                                 R_Mesh_TexBind(0, layer->texture);
9706                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9707                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9708                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9709                         }
9710                         else
9711                         {
9712                                 R_Mesh_TexBind(0, 0);
9713                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9714                         }
9715                         // generate a color array for the fog pass
9716                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9717                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9718                         RSurf_DrawBatch();
9719                         break;
9720                 default:
9721                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9722                 }
9723         }
9724         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9725         {
9726                 GL_DepthFunc(GL_LEQUAL);
9727                 GL_AlphaTest(false);
9728         }
9729 }
9730
9731 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9732 {
9733         int vi;
9734         int j;
9735         r_vertexgeneric_t *batchvertex;
9736         float c[4];
9737
9738 //      R_Mesh_ResetTextureState();
9739         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9740
9741         if(rsurface.texture && rsurface.texture->currentskinframe)
9742         {
9743                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9744                 c[3] *= rsurface.texture->currentalpha;
9745         }
9746         else
9747         {
9748                 c[0] = 1;
9749                 c[1] = 0;
9750                 c[2] = 1;
9751                 c[3] = 1;
9752         }
9753
9754         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9755         {
9756                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9757                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9758                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9759         }
9760
9761         // brighten it up (as texture value 127 means "unlit")
9762         c[0] *= 2 * r_refdef.view.colorscale;
9763         c[1] *= 2 * r_refdef.view.colorscale;
9764         c[2] *= 2 * r_refdef.view.colorscale;
9765
9766         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9767                 c[3] *= r_wateralpha.value;
9768
9769         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9770         {
9771                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9772                 GL_DepthMask(false);
9773         }
9774         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9775         {
9776                 GL_BlendFunc(GL_ONE, GL_ONE);
9777                 GL_DepthMask(false);
9778         }
9779         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9780         {
9781                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9782                 GL_DepthMask(false);
9783         }
9784         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9785         {
9786                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9787                 GL_DepthMask(false);
9788         }
9789         else
9790         {
9791                 GL_BlendFunc(GL_ONE, GL_ZERO);
9792                 GL_DepthMask(writedepth);
9793         }
9794
9795         if (r_showsurfaces.integer == 3)
9796         {
9797                 rsurface.passcolor4f = NULL;
9798
9799                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9800                 {
9801                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9802
9803                         rsurface.passcolor4f = NULL;
9804                         rsurface.passcolor4f_vertexbuffer = 0;
9805                         rsurface.passcolor4f_bufferoffset = 0;
9806                 }
9807                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9808                 {
9809                         qboolean applycolor = true;
9810                         float one = 1.0;
9811
9812                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9813
9814                         r_refdef.lightmapintensity = 1;
9815                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9816                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9817                 }
9818                 else if (FAKELIGHT_ENABLED)
9819                 {
9820                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9821
9822                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9823                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9824                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9825                 }
9826                 else
9827                 {
9828                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9829
9830                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9831                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9832                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9833                 }
9834
9835                 if(!rsurface.passcolor4f)
9836                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9837
9838                 RSurf_DrawBatch_GL11_ApplyAmbient();
9839                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9840                 if(r_refdef.fogenabled)
9841                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9842                 RSurf_DrawBatch_GL11_ClampColor();
9843
9844                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9845                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9846                 RSurf_DrawBatch();
9847         }
9848         else if (!r_refdef.view.showdebug)
9849         {
9850                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9851                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9852                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9853                 {
9854                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9855                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9856                 }
9857                 R_Mesh_PrepareVertices_Generic_Unlock();
9858                 RSurf_DrawBatch();
9859         }
9860         else if (r_showsurfaces.integer == 4)
9861         {
9862                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9863                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9864                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9865                 {
9866                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9867                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9868                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9869                 }
9870                 R_Mesh_PrepareVertices_Generic_Unlock();
9871                 RSurf_DrawBatch();
9872         }
9873         else if (r_showsurfaces.integer == 2)
9874         {
9875                 const int *e;
9876                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9877                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9878                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9879                 {
9880                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9881                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9882                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9883                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9884                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9885                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9886                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9887                 }
9888                 R_Mesh_PrepareVertices_Generic_Unlock();
9889                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9890         }
9891         else
9892         {
9893                 int texturesurfaceindex;
9894                 int k;
9895                 const msurface_t *surface;
9896                 float surfacecolor4f[4];
9897                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9898                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9899                 vi = 0;
9900                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9901                 {
9902                         surface = texturesurfacelist[texturesurfaceindex];
9903                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9904                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9905                         for (j = 0;j < surface->num_vertices;j++)
9906                         {
9907                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9908                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9909                                 vi++;
9910                         }
9911                 }
9912                 R_Mesh_PrepareVertices_Generic_Unlock();
9913                 RSurf_DrawBatch();
9914         }
9915 }
9916
9917 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9918 {
9919         CHECKGLERROR
9920         RSurf_SetupDepthAndCulling();
9921         if (r_showsurfaces.integer)
9922         {
9923                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9924                 return;
9925         }
9926         switch (vid.renderpath)
9927         {
9928         case RENDERPATH_GL20:
9929         case RENDERPATH_D3D9:
9930         case RENDERPATH_D3D10:
9931         case RENDERPATH_D3D11:
9932         case RENDERPATH_SOFT:
9933         case RENDERPATH_GLES2:
9934                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9935                 break;
9936         case RENDERPATH_GL13:
9937         case RENDERPATH_GLES1:
9938                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9939                 break;
9940         case RENDERPATH_GL11:
9941                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9942                 break;
9943         }
9944         CHECKGLERROR
9945 }
9946
9947 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9948 {
9949         CHECKGLERROR
9950         RSurf_SetupDepthAndCulling();
9951         if (r_showsurfaces.integer)
9952         {
9953                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9954                 return;
9955         }
9956         switch (vid.renderpath)
9957         {
9958         case RENDERPATH_GL20:
9959         case RENDERPATH_D3D9:
9960         case RENDERPATH_D3D10:
9961         case RENDERPATH_D3D11:
9962         case RENDERPATH_SOFT:
9963         case RENDERPATH_GLES2:
9964                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9965                 break;
9966         case RENDERPATH_GL13:
9967         case RENDERPATH_GLES1:
9968                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9969                 break;
9970         case RENDERPATH_GL11:
9971                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9972                 break;
9973         }
9974         CHECKGLERROR
9975 }
9976
9977 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9978 {
9979         int i, j;
9980         int texturenumsurfaces, endsurface;
9981         texture_t *texture;
9982         const msurface_t *surface;
9983         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
9984
9985         // if the model is static it doesn't matter what value we give for
9986         // wantnormals and wanttangents, so this logic uses only rules applicable
9987         // to a model, knowing that they are meaningless otherwise
9988         if (ent == r_refdef.scene.worldentity)
9989                 RSurf_ActiveWorldEntity();
9990         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9991                 RSurf_ActiveModelEntity(ent, false, false, false);
9992         else
9993         {
9994                 switch (vid.renderpath)
9995                 {
9996                 case RENDERPATH_GL20:
9997                 case RENDERPATH_D3D9:
9998                 case RENDERPATH_D3D10:
9999                 case RENDERPATH_D3D11:
10000                 case RENDERPATH_SOFT:
10001                 case RENDERPATH_GLES2:
10002                         RSurf_ActiveModelEntity(ent, true, true, false);
10003                         break;
10004                 case RENDERPATH_GL11:
10005                 case RENDERPATH_GL13:
10006                 case RENDERPATH_GLES1:
10007                         RSurf_ActiveModelEntity(ent, true, false, false);
10008                         break;
10009                 }
10010         }
10011
10012         if (r_transparentdepthmasking.integer)
10013         {
10014                 qboolean setup = false;
10015                 for (i = 0;i < numsurfaces;i = j)
10016                 {
10017                         j = i + 1;
10018                         surface = rsurface.modelsurfaces + surfacelist[i];
10019                         texture = surface->texture;
10020                         rsurface.texture = R_GetCurrentTexture(texture);
10021                         rsurface.lightmaptexture = NULL;
10022                         rsurface.deluxemaptexture = NULL;
10023                         rsurface.uselightmaptexture = false;
10024                         // scan ahead until we find a different texture
10025                         endsurface = min(i + 1024, numsurfaces);
10026                         texturenumsurfaces = 0;
10027                         texturesurfacelist[texturenumsurfaces++] = surface;
10028                         for (;j < endsurface;j++)
10029                         {
10030                                 surface = rsurface.modelsurfaces + surfacelist[j];
10031                                 if (texture != surface->texture)
10032                                         break;
10033                                 texturesurfacelist[texturenumsurfaces++] = surface;
10034                         }
10035                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10036                                 continue;
10037                         // render the range of surfaces as depth
10038                         if (!setup)
10039                         {
10040                                 setup = true;
10041                                 GL_ColorMask(0,0,0,0);
10042                                 GL_Color(1,1,1,1);
10043                                 GL_DepthTest(true);
10044                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10045                                 GL_DepthMask(true);
10046 //                              R_Mesh_ResetTextureState();
10047                                 R_SetupShader_DepthOrShadow();
10048                         }
10049                         RSurf_SetupDepthAndCulling();
10050                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10051                         if (rsurface.batchvertex3fbuffer)
10052                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10053                         else
10054                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10055                         RSurf_DrawBatch();
10056                 }
10057                 if (setup)
10058                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10059         }
10060
10061         for (i = 0;i < numsurfaces;i = j)
10062         {
10063                 j = i + 1;
10064                 surface = rsurface.modelsurfaces + surfacelist[i];
10065                 texture = surface->texture;
10066                 rsurface.texture = R_GetCurrentTexture(texture);
10067                 // scan ahead until we find a different texture
10068                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10069                 texturenumsurfaces = 0;
10070                 texturesurfacelist[texturenumsurfaces++] = surface;
10071                 if(FAKELIGHT_ENABLED)
10072                 {
10073                         rsurface.lightmaptexture = NULL;
10074                         rsurface.deluxemaptexture = NULL;
10075                         rsurface.uselightmaptexture = false;
10076                         for (;j < endsurface;j++)
10077                         {
10078                                 surface = rsurface.modelsurfaces + surfacelist[j];
10079                                 if (texture != surface->texture)
10080                                         break;
10081                                 texturesurfacelist[texturenumsurfaces++] = surface;
10082                         }
10083                 }
10084                 else
10085                 {
10086                         rsurface.lightmaptexture = surface->lightmaptexture;
10087                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10088                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10089                         for (;j < endsurface;j++)
10090                         {
10091                                 surface = rsurface.modelsurfaces + surfacelist[j];
10092                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10093                                         break;
10094                                 texturesurfacelist[texturenumsurfaces++] = surface;
10095                         }
10096                 }
10097                 // render the range of surfaces
10098                 if (ent == r_refdef.scene.worldentity)
10099                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10100                 else
10101                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10102         }
10103         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10104 }
10105
10106 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10107 {
10108         // transparent surfaces get pushed off into the transparent queue
10109         int surfacelistindex;
10110         const msurface_t *surface;
10111         vec3_t tempcenter, center;
10112         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10113         {
10114                 surface = texturesurfacelist[surfacelistindex];
10115                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10116                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10117                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10118                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10119                 if (queueentity->transparent_offset) // transparent offset
10120                 {
10121                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10122                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10123                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10124                 }
10125                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10126         }
10127 }
10128
10129 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10130 {
10131         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10132                 return;
10133         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10134                 return;
10135         RSurf_SetupDepthAndCulling();
10136         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10137         if (rsurface.batchvertex3fbuffer)
10138                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10139         else
10140                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10141         RSurf_DrawBatch();
10142 }
10143
10144 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10145 {
10146         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10147         CHECKGLERROR
10148         if (depthonly)
10149                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10150         else if (prepass)
10151         {
10152                 if (!rsurface.texture->currentnumlayers)
10153                         return;
10154                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10155                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10156                 else
10157                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10158         }
10159         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10160                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10161         else if (!rsurface.texture->currentnumlayers)
10162                 return;
10163         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10164         {
10165                 // in the deferred case, transparent surfaces were queued during prepass
10166                 if (!r_shadow_usingdeferredprepass)
10167                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10168         }
10169         else
10170         {
10171                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10172                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10173         }
10174         CHECKGLERROR
10175 }
10176
10177 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10178 {
10179         int i, j;
10180         texture_t *texture;
10181         R_FrameData_SetMark();
10182         // break the surface list down into batches by texture and use of lightmapping
10183         for (i = 0;i < numsurfaces;i = j)
10184         {
10185                 j = i + 1;
10186                 // texture is the base texture pointer, rsurface.texture is the
10187                 // current frame/skin the texture is directing us to use (for example
10188                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10189                 // use skin 1 instead)
10190                 texture = surfacelist[i]->texture;
10191                 rsurface.texture = R_GetCurrentTexture(texture);
10192                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10193                 {
10194                         // if this texture is not the kind we want, skip ahead to the next one
10195                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10196                                 ;
10197                         continue;
10198                 }
10199                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10200                 {
10201                         rsurface.lightmaptexture = NULL;
10202                         rsurface.deluxemaptexture = NULL;
10203                         rsurface.uselightmaptexture = false;
10204                         // simply scan ahead until we find a different texture or lightmap state
10205                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10206                                 ;
10207                 }
10208                 else
10209                 {
10210                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10211                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10212                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10213                         // simply scan ahead until we find a different texture or lightmap state
10214                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10215                                 ;
10216                 }
10217                 // render the range of surfaces
10218                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10219         }
10220         R_FrameData_ReturnToMark();
10221 }
10222
10223 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10224 {
10225         CHECKGLERROR
10226         if (depthonly)
10227                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10228         else if (prepass)
10229         {
10230                 if (!rsurface.texture->currentnumlayers)
10231                         return;
10232                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10233                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10234                 else
10235                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10236         }
10237         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10238                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10239         else if (!rsurface.texture->currentnumlayers)
10240                 return;
10241         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10242         {
10243                 // in the deferred case, transparent surfaces were queued during prepass
10244                 if (!r_shadow_usingdeferredprepass)
10245                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10246         }
10247         else
10248         {
10249                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10250                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10251         }
10252         CHECKGLERROR
10253 }
10254
10255 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10256 {
10257         int i, j;
10258         texture_t *texture;
10259         R_FrameData_SetMark();
10260         // break the surface list down into batches by texture and use of lightmapping
10261         for (i = 0;i < numsurfaces;i = j)
10262         {
10263                 j = i + 1;
10264                 // texture is the base texture pointer, rsurface.texture is the
10265                 // current frame/skin the texture is directing us to use (for example
10266                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10267                 // use skin 1 instead)
10268                 texture = surfacelist[i]->texture;
10269                 rsurface.texture = R_GetCurrentTexture(texture);
10270                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10271                 {
10272                         // if this texture is not the kind we want, skip ahead to the next one
10273                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10274                                 ;
10275                         continue;
10276                 }
10277                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10278                 {
10279                         rsurface.lightmaptexture = NULL;
10280                         rsurface.deluxemaptexture = NULL;
10281                         rsurface.uselightmaptexture = false;
10282                         // simply scan ahead until we find a different texture or lightmap state
10283                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10284                                 ;
10285                 }
10286                 else
10287                 {
10288                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10289                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10290                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10291                         // simply scan ahead until we find a different texture or lightmap state
10292                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10293                                 ;
10294                 }
10295                 // render the range of surfaces
10296                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10297         }
10298         R_FrameData_ReturnToMark();
10299 }
10300
10301 float locboxvertex3f[6*4*3] =
10302 {
10303         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10304         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10305         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10306         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10307         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10308         1,0,0, 0,0,0, 0,1,0, 1,1,0
10309 };
10310
10311 unsigned short locboxelements[6*2*3] =
10312 {
10313          0, 1, 2, 0, 2, 3,
10314          4, 5, 6, 4, 6, 7,
10315          8, 9,10, 8,10,11,
10316         12,13,14, 12,14,15,
10317         16,17,18, 16,18,19,
10318         20,21,22, 20,22,23
10319 };
10320
10321 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10322 {
10323         int i, j;
10324         cl_locnode_t *loc = (cl_locnode_t *)ent;
10325         vec3_t mins, size;
10326         float vertex3f[6*4*3];
10327         CHECKGLERROR
10328         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10329         GL_DepthMask(false);
10330         GL_DepthRange(0, 1);
10331         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10332         GL_DepthTest(true);
10333         GL_CullFace(GL_NONE);
10334         R_EntityMatrix(&identitymatrix);
10335
10336 //      R_Mesh_ResetTextureState();
10337
10338         i = surfacelist[0];
10339         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10340                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10341                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10342                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10343
10344         if (VectorCompare(loc->mins, loc->maxs))
10345         {
10346                 VectorSet(size, 2, 2, 2);
10347                 VectorMA(loc->mins, -0.5f, size, mins);
10348         }
10349         else
10350         {
10351                 VectorCopy(loc->mins, mins);
10352                 VectorSubtract(loc->maxs, loc->mins, size);
10353         }
10354
10355         for (i = 0;i < 6*4*3;)
10356                 for (j = 0;j < 3;j++, i++)
10357                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10358
10359         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10360         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10361         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10362 }
10363
10364 void R_DrawLocs(void)
10365 {
10366         int index;
10367         cl_locnode_t *loc, *nearestloc;
10368         vec3_t center;
10369         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10370         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10371         {
10372                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10373                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10374         }
10375 }
10376
10377 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10378 {
10379         if (decalsystem->decals)
10380                 Mem_Free(decalsystem->decals);
10381         memset(decalsystem, 0, sizeof(*decalsystem));
10382 }
10383
10384 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)
10385 {
10386         tridecal_t *decal;
10387         tridecal_t *decals;
10388         int i;
10389
10390         // expand or initialize the system
10391         if (decalsystem->maxdecals <= decalsystem->numdecals)
10392         {
10393                 decalsystem_t old = *decalsystem;
10394                 qboolean useshortelements;
10395                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10396                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10397                 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)));
10398                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10399                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10400                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10401                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10402                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10403                 if (decalsystem->numdecals)
10404                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10405                 if (old.decals)
10406                         Mem_Free(old.decals);
10407                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10408                         decalsystem->element3i[i] = i;
10409                 if (useshortelements)
10410                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10411                                 decalsystem->element3s[i] = i;
10412         }
10413
10414         // grab a decal and search for another free slot for the next one
10415         decals = decalsystem->decals;
10416         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10417         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10418                 ;
10419         decalsystem->freedecal = i;
10420         if (decalsystem->numdecals <= i)
10421                 decalsystem->numdecals = i + 1;
10422
10423         // initialize the decal
10424         decal->lived = 0;
10425         decal->triangleindex = triangleindex;
10426         decal->surfaceindex = surfaceindex;
10427         decal->decalsequence = decalsequence;
10428         decal->color4f[0][0] = c0[0];
10429         decal->color4f[0][1] = c0[1];
10430         decal->color4f[0][2] = c0[2];
10431         decal->color4f[0][3] = 1;
10432         decal->color4f[1][0] = c1[0];
10433         decal->color4f[1][1] = c1[1];
10434         decal->color4f[1][2] = c1[2];
10435         decal->color4f[1][3] = 1;
10436         decal->color4f[2][0] = c2[0];
10437         decal->color4f[2][1] = c2[1];
10438         decal->color4f[2][2] = c2[2];
10439         decal->color4f[2][3] = 1;
10440         decal->vertex3f[0][0] = v0[0];
10441         decal->vertex3f[0][1] = v0[1];
10442         decal->vertex3f[0][2] = v0[2];
10443         decal->vertex3f[1][0] = v1[0];
10444         decal->vertex3f[1][1] = v1[1];
10445         decal->vertex3f[1][2] = v1[2];
10446         decal->vertex3f[2][0] = v2[0];
10447         decal->vertex3f[2][1] = v2[1];
10448         decal->vertex3f[2][2] = v2[2];
10449         decal->texcoord2f[0][0] = t0[0];
10450         decal->texcoord2f[0][1] = t0[1];
10451         decal->texcoord2f[1][0] = t1[0];
10452         decal->texcoord2f[1][1] = t1[1];
10453         decal->texcoord2f[2][0] = t2[0];
10454         decal->texcoord2f[2][1] = t2[1];
10455         TriangleNormal(v0, v1, v2, decal->plane);
10456         VectorNormalize(decal->plane);
10457         decal->plane[3] = DotProduct(v0, decal->plane);
10458 }
10459
10460 extern cvar_t cl_decals_bias;
10461 extern cvar_t cl_decals_models;
10462 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10463 // baseparms, parms, temps
10464 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)
10465 {
10466         int cornerindex;
10467         int index;
10468         float v[9][3];
10469         const float *vertex3f;
10470         const float *normal3f;
10471         int numpoints;
10472         float points[2][9][3];
10473         float temp[3];
10474         float tc[9][2];
10475         float f;
10476         float c[9][4];
10477         const int *e;
10478
10479         e = rsurface.modelelement3i + 3*triangleindex;
10480
10481         vertex3f = rsurface.modelvertex3f;
10482         normal3f = rsurface.modelnormal3f;
10483
10484         if (normal3f)
10485         {
10486                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10487                 {
10488                         index = 3*e[cornerindex];
10489                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10490                 }
10491         }
10492         else
10493         {
10494                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10495                 {
10496                         index = 3*e[cornerindex];
10497                         VectorCopy(vertex3f + index, v[cornerindex]);
10498                 }
10499         }
10500
10501         // cull backfaces
10502         //TriangleNormal(v[0], v[1], v[2], normal);
10503         //if (DotProduct(normal, localnormal) < 0.0f)
10504         //      continue;
10505         // clip by each of the box planes formed from the projection matrix
10506         // if anything survives, we emit the decal
10507         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]);
10508         if (numpoints < 3)
10509                 return;
10510         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]);
10511         if (numpoints < 3)
10512                 return;
10513         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]);
10514         if (numpoints < 3)
10515                 return;
10516         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]);
10517         if (numpoints < 3)
10518                 return;
10519         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]);
10520         if (numpoints < 3)
10521                 return;
10522         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]);
10523         if (numpoints < 3)
10524                 return;
10525         // some part of the triangle survived, so we have to accept it...
10526         if (dynamic)
10527         {
10528                 // dynamic always uses the original triangle
10529                 numpoints = 3;
10530                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10531                 {
10532                         index = 3*e[cornerindex];
10533                         VectorCopy(vertex3f + index, v[cornerindex]);
10534                 }
10535         }
10536         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10537         {
10538                 // convert vertex positions to texcoords
10539                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10540                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10541                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10542                 // calculate distance fade from the projection origin
10543                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10544                 f = bound(0.0f, f, 1.0f);
10545                 c[cornerindex][0] = r * f;
10546                 c[cornerindex][1] = g * f;
10547                 c[cornerindex][2] = b * f;
10548                 c[cornerindex][3] = 1.0f;
10549                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10550         }
10551         if (dynamic)
10552                 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);
10553         else
10554                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10555                         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);
10556 }
10557 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)
10558 {
10559         matrix4x4_t projection;
10560         decalsystem_t *decalsystem;
10561         qboolean dynamic;
10562         dp_model_t *model;
10563         const msurface_t *surface;
10564         const msurface_t *surfaces;
10565         const int *surfacelist;
10566         const texture_t *texture;
10567         int numtriangles;
10568         int numsurfacelist;
10569         int surfacelistindex;
10570         int surfaceindex;
10571         int triangleindex;
10572         float localorigin[3];
10573         float localnormal[3];
10574         float localmins[3];
10575         float localmaxs[3];
10576         float localsize;
10577         //float normal[3];
10578         float planes[6][4];
10579         float angles[3];
10580         bih_t *bih;
10581         int bih_triangles_count;
10582         int bih_triangles[256];
10583         int bih_surfaces[256];
10584
10585         decalsystem = &ent->decalsystem;
10586         model = ent->model;
10587         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10588         {
10589                 R_DecalSystem_Reset(&ent->decalsystem);
10590                 return;
10591         }
10592
10593         if (!model->brush.data_leafs && !cl_decals_models.integer)
10594         {
10595                 if (decalsystem->model)
10596                         R_DecalSystem_Reset(decalsystem);
10597                 return;
10598         }
10599
10600         if (decalsystem->model != model)
10601                 R_DecalSystem_Reset(decalsystem);
10602         decalsystem->model = model;
10603
10604         RSurf_ActiveModelEntity(ent, true, false, false);
10605
10606         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10607         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10608         VectorNormalize(localnormal);
10609         localsize = worldsize*rsurface.inversematrixscale;
10610         localmins[0] = localorigin[0] - localsize;
10611         localmins[1] = localorigin[1] - localsize;
10612         localmins[2] = localorigin[2] - localsize;
10613         localmaxs[0] = localorigin[0] + localsize;
10614         localmaxs[1] = localorigin[1] + localsize;
10615         localmaxs[2] = localorigin[2] + localsize;
10616
10617         //VectorCopy(localnormal, planes[4]);
10618         //VectorVectors(planes[4], planes[2], planes[0]);
10619         AnglesFromVectors(angles, localnormal, NULL, false);
10620         AngleVectors(angles, planes[0], planes[2], planes[4]);
10621         VectorNegate(planes[0], planes[1]);
10622         VectorNegate(planes[2], planes[3]);
10623         VectorNegate(planes[4], planes[5]);
10624         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10625         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10626         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10627         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10628         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10629         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10630
10631 #if 1
10632 // works
10633 {
10634         matrix4x4_t forwardprojection;
10635         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10636         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10637 }
10638 #else
10639 // broken
10640 {
10641         float projectionvector[4][3];
10642         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10643         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10644         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10645         projectionvector[0][0] = planes[0][0] * ilocalsize;
10646         projectionvector[0][1] = planes[1][0] * ilocalsize;
10647         projectionvector[0][2] = planes[2][0] * ilocalsize;
10648         projectionvector[1][0] = planes[0][1] * ilocalsize;
10649         projectionvector[1][1] = planes[1][1] * ilocalsize;
10650         projectionvector[1][2] = planes[2][1] * ilocalsize;
10651         projectionvector[2][0] = planes[0][2] * ilocalsize;
10652         projectionvector[2][1] = planes[1][2] * ilocalsize;
10653         projectionvector[2][2] = planes[2][2] * ilocalsize;
10654         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10655         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10656         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10657         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10658 }
10659 #endif
10660
10661         dynamic = model->surfmesh.isanimated;
10662         numsurfacelist = model->nummodelsurfaces;
10663         surfacelist = model->sortedmodelsurfaces;
10664         surfaces = model->data_surfaces;
10665
10666         bih = NULL;
10667         bih_triangles_count = -1;
10668         if(!dynamic)
10669         {
10670                 if(model->render_bih.numleafs)
10671                         bih = &model->render_bih;
10672                 else if(model->collision_bih.numleafs)
10673                         bih = &model->collision_bih;
10674         }
10675         if(bih)
10676                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10677         if(bih_triangles_count == 0)
10678                 return;
10679         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10680                 return;
10681         if(bih_triangles_count > 0)
10682         {
10683                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10684                 {
10685                         surfaceindex = bih_surfaces[triangleindex];
10686                         surface = surfaces + surfaceindex;
10687                         texture = surface->texture;
10688                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10689                                 continue;
10690                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10691                                 continue;
10692                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10693                 }
10694         }
10695         else
10696         {
10697                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10698                 {
10699                         surfaceindex = surfacelist[surfacelistindex];
10700                         surface = surfaces + surfaceindex;
10701                         // check cull box first because it rejects more than any other check
10702                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10703                                 continue;
10704                         // skip transparent surfaces
10705                         texture = surface->texture;
10706                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10707                                 continue;
10708                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10709                                 continue;
10710                         numtriangles = surface->num_triangles;
10711                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10712                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10713                 }
10714         }
10715 }
10716
10717 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10718 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)
10719 {
10720         int renderentityindex;
10721         float worldmins[3];
10722         float worldmaxs[3];
10723         entity_render_t *ent;
10724
10725         if (!cl_decals_newsystem.integer)
10726                 return;
10727
10728         worldmins[0] = worldorigin[0] - worldsize;
10729         worldmins[1] = worldorigin[1] - worldsize;
10730         worldmins[2] = worldorigin[2] - worldsize;
10731         worldmaxs[0] = worldorigin[0] + worldsize;
10732         worldmaxs[1] = worldorigin[1] + worldsize;
10733         worldmaxs[2] = worldorigin[2] + worldsize;
10734
10735         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10736
10737         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10738         {
10739                 ent = r_refdef.scene.entities[renderentityindex];
10740                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10741                         continue;
10742
10743                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10744         }
10745 }
10746
10747 typedef struct r_decalsystem_splatqueue_s
10748 {
10749         vec3_t worldorigin;
10750         vec3_t worldnormal;
10751         float color[4];
10752         float tcrange[4];
10753         float worldsize;
10754         int decalsequence;
10755 }
10756 r_decalsystem_splatqueue_t;
10757
10758 int r_decalsystem_numqueued = 0;
10759 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10760
10761 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)
10762 {
10763         r_decalsystem_splatqueue_t *queue;
10764
10765         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10766                 return;
10767
10768         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10769         VectorCopy(worldorigin, queue->worldorigin);
10770         VectorCopy(worldnormal, queue->worldnormal);
10771         Vector4Set(queue->color, r, g, b, a);
10772         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10773         queue->worldsize = worldsize;
10774         queue->decalsequence = cl.decalsequence++;
10775 }
10776
10777 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10778 {
10779         int i;
10780         r_decalsystem_splatqueue_t *queue;
10781
10782         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10783                 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);
10784         r_decalsystem_numqueued = 0;
10785 }
10786
10787 extern cvar_t cl_decals_max;
10788 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10789 {
10790         int i;
10791         decalsystem_t *decalsystem = &ent->decalsystem;
10792         int numdecals;
10793         int killsequence;
10794         tridecal_t *decal;
10795         float frametime;
10796         float lifetime;
10797
10798         if (!decalsystem->numdecals)
10799                 return;
10800
10801         if (r_showsurfaces.integer)
10802                 return;
10803
10804         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10805         {
10806                 R_DecalSystem_Reset(decalsystem);
10807                 return;
10808         }
10809
10810         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10811         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10812
10813         if (decalsystem->lastupdatetime)
10814                 frametime = (cl.time - decalsystem->lastupdatetime);
10815         else
10816                 frametime = 0;
10817         decalsystem->lastupdatetime = cl.time;
10818         decal = decalsystem->decals;
10819         numdecals = decalsystem->numdecals;
10820
10821         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10822         {
10823                 if (decal->color4f[0][3])
10824                 {
10825                         decal->lived += frametime;
10826                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10827                         {
10828                                 memset(decal, 0, sizeof(*decal));
10829                                 if (decalsystem->freedecal > i)
10830                                         decalsystem->freedecal = i;
10831                         }
10832                 }
10833         }
10834         decal = decalsystem->decals;
10835         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10836                 numdecals--;
10837
10838         // collapse the array by shuffling the tail decals into the gaps
10839         for (;;)
10840         {
10841                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10842                         decalsystem->freedecal++;
10843                 if (decalsystem->freedecal == numdecals)
10844                         break;
10845                 decal[decalsystem->freedecal] = decal[--numdecals];
10846         }
10847
10848         decalsystem->numdecals = numdecals;
10849
10850         if (numdecals <= 0)
10851         {
10852                 // if there are no decals left, reset decalsystem
10853                 R_DecalSystem_Reset(decalsystem);
10854         }
10855 }
10856
10857 extern skinframe_t *decalskinframe;
10858 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10859 {
10860         int i;
10861         decalsystem_t *decalsystem = &ent->decalsystem;
10862         int numdecals;
10863         tridecal_t *decal;
10864         float faderate;
10865         float alpha;
10866         float *v3f;
10867         float *c4f;
10868         float *t2f;
10869         const int *e;
10870         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10871         int numtris = 0;
10872
10873         numdecals = decalsystem->numdecals;
10874         if (!numdecals)
10875                 return;
10876
10877         if (r_showsurfaces.integer)
10878                 return;
10879
10880         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10881         {
10882                 R_DecalSystem_Reset(decalsystem);
10883                 return;
10884         }
10885
10886         // if the model is static it doesn't matter what value we give for
10887         // wantnormals and wanttangents, so this logic uses only rules applicable
10888         // to a model, knowing that they are meaningless otherwise
10889         if (ent == r_refdef.scene.worldentity)
10890                 RSurf_ActiveWorldEntity();
10891         else
10892                 RSurf_ActiveModelEntity(ent, false, false, false);
10893
10894         decalsystem->lastupdatetime = cl.time;
10895         decal = decalsystem->decals;
10896
10897         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10898
10899         // update vertex positions for animated models
10900         v3f = decalsystem->vertex3f;
10901         c4f = decalsystem->color4f;
10902         t2f = decalsystem->texcoord2f;
10903         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10904         {
10905                 if (!decal->color4f[0][3])
10906                         continue;
10907
10908                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10909                         continue;
10910
10911                 // skip backfaces
10912                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10913                         continue;
10914
10915                 // update color values for fading decals
10916                 if (decal->lived >= cl_decals_time.value)
10917                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10918                 else
10919                         alpha = 1.0f;
10920
10921                 c4f[ 0] = decal->color4f[0][0] * alpha;
10922                 c4f[ 1] = decal->color4f[0][1] * alpha;
10923                 c4f[ 2] = decal->color4f[0][2] * alpha;
10924                 c4f[ 3] = 1;
10925                 c4f[ 4] = decal->color4f[1][0] * alpha;
10926                 c4f[ 5] = decal->color4f[1][1] * alpha;
10927                 c4f[ 6] = decal->color4f[1][2] * alpha;
10928                 c4f[ 7] = 1;
10929                 c4f[ 8] = decal->color4f[2][0] * alpha;
10930                 c4f[ 9] = decal->color4f[2][1] * alpha;
10931                 c4f[10] = decal->color4f[2][2] * alpha;
10932                 c4f[11] = 1;
10933
10934                 t2f[0] = decal->texcoord2f[0][0];
10935                 t2f[1] = decal->texcoord2f[0][1];
10936                 t2f[2] = decal->texcoord2f[1][0];
10937                 t2f[3] = decal->texcoord2f[1][1];
10938                 t2f[4] = decal->texcoord2f[2][0];
10939                 t2f[5] = decal->texcoord2f[2][1];
10940
10941                 // update vertex positions for animated models
10942                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10943                 {
10944                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10945                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10946                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10947                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10948                 }
10949                 else
10950                 {
10951                         VectorCopy(decal->vertex3f[0], v3f);
10952                         VectorCopy(decal->vertex3f[1], v3f + 3);
10953                         VectorCopy(decal->vertex3f[2], v3f + 6);
10954                 }
10955
10956                 if (r_refdef.fogenabled)
10957                 {
10958                         alpha = RSurf_FogVertex(v3f);
10959                         VectorScale(c4f, alpha, c4f);
10960                         alpha = RSurf_FogVertex(v3f + 3);
10961                         VectorScale(c4f + 4, alpha, c4f + 4);
10962                         alpha = RSurf_FogVertex(v3f + 6);
10963                         VectorScale(c4f + 8, alpha, c4f + 8);
10964                 }
10965
10966                 v3f += 9;
10967                 c4f += 12;
10968                 t2f += 6;
10969                 numtris++;
10970         }
10971
10972         if (numtris > 0)
10973         {
10974                 r_refdef.stats.drawndecals += numtris;
10975
10976                 // now render the decals all at once
10977                 // (this assumes they all use one particle font texture!)
10978                 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);
10979 //              R_Mesh_ResetTextureState();
10980                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10981                 GL_DepthMask(false);
10982                 GL_DepthRange(0, 1);
10983                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10984                 GL_DepthTest(true);
10985                 GL_CullFace(GL_NONE);
10986                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10987                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10988                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10989         }
10990 }
10991
10992 static void R_DrawModelDecals(void)
10993 {
10994         int i, numdecals;
10995
10996         // fade faster when there are too many decals
10997         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10998         for (i = 0;i < r_refdef.scene.numentities;i++)
10999                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11000
11001         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11002         for (i = 0;i < r_refdef.scene.numentities;i++)
11003                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11004                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11005
11006         R_DecalSystem_ApplySplatEntitiesQueue();
11007
11008         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11009         for (i = 0;i < r_refdef.scene.numentities;i++)
11010                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11011
11012         r_refdef.stats.totaldecals += numdecals;
11013
11014         if (r_showsurfaces.integer)
11015                 return;
11016
11017         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11018
11019         for (i = 0;i < r_refdef.scene.numentities;i++)
11020         {
11021                 if (!r_refdef.viewcache.entityvisible[i])
11022                         continue;
11023                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11024                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11025         }
11026 }
11027
11028 extern cvar_t mod_collision_bih;
11029 void R_DrawDebugModel(void)
11030 {
11031         entity_render_t *ent = rsurface.entity;
11032         int i, j, k, l, flagsmask;
11033         const msurface_t *surface;
11034         dp_model_t *model = ent->model;
11035         vec3_t v;
11036
11037         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11038                 return;
11039
11040         if (r_showoverdraw.value > 0)
11041         {
11042                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11043                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11044                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11045                 GL_DepthTest(false);
11046                 GL_DepthMask(false);
11047                 GL_DepthRange(0, 1);
11048                 GL_BlendFunc(GL_ONE, GL_ONE);
11049                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11050                 {
11051                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11052                                 continue;
11053                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11054                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11055                         {
11056                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11057                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11058                                 if (!rsurface.texture->currentlayers->depthmask)
11059                                         GL_Color(c, 0, 0, 1.0f);
11060                                 else if (ent == r_refdef.scene.worldentity)
11061                                         GL_Color(c, c, c, 1.0f);
11062                                 else
11063                                         GL_Color(0, c, 0, 1.0f);
11064                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11065                                 RSurf_DrawBatch();
11066                         }
11067                 }
11068                 rsurface.texture = NULL;
11069         }
11070
11071         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11072
11073 //      R_Mesh_ResetTextureState();
11074         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11075         GL_DepthRange(0, 1);
11076         GL_DepthTest(!r_showdisabledepthtest.integer);
11077         GL_DepthMask(false);
11078         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11079
11080         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11081         {
11082                 int triangleindex;
11083                 int bihleafindex;
11084                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11085                 const q3mbrush_t *brush;
11086                 const bih_t *bih = &model->collision_bih;
11087                 const bih_leaf_t *bihleaf;
11088                 float vertex3f[3][3];
11089                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11090                 cullbox = false;
11091                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11092                 {
11093                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11094                                 continue;
11095                         switch (bihleaf->type)
11096                         {
11097                         case BIH_BRUSH:
11098                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11099                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11100                                 {
11101                                         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);
11102                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11103                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11104                                 }
11105                                 break;
11106                         case BIH_COLLISIONTRIANGLE:
11107                                 triangleindex = bihleaf->itemindex;
11108                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11109                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11110                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11111                                 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);
11112                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11113                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11114                                 break;
11115                         case BIH_RENDERTRIANGLE:
11116                                 triangleindex = bihleaf->itemindex;
11117                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11118                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11119                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11120                                 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);
11121                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11122                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11123                                 break;
11124                         }
11125                 }
11126         }
11127
11128         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11129
11130         if (r_showtris.integer && qglPolygonMode)
11131         {
11132                 if (r_showdisabledepthtest.integer)
11133                 {
11134                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11135                         GL_DepthMask(false);
11136                 }
11137                 else
11138                 {
11139                         GL_BlendFunc(GL_ONE, GL_ZERO);
11140                         GL_DepthMask(true);
11141                 }
11142                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11143                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11144                 {
11145                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11146                                 continue;
11147                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11148                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11149                         {
11150                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11151                                 if (!rsurface.texture->currentlayers->depthmask)
11152                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11153                                 else if (ent == r_refdef.scene.worldentity)
11154                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11155                                 else
11156                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11157                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11158                                 RSurf_DrawBatch();
11159                         }
11160                 }
11161                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11162                 rsurface.texture = NULL;
11163         }
11164
11165         if (r_shownormals.value != 0 && qglBegin)
11166         {
11167                 if (r_showdisabledepthtest.integer)
11168                 {
11169                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11170                         GL_DepthMask(false);
11171                 }
11172                 else
11173                 {
11174                         GL_BlendFunc(GL_ONE, GL_ZERO);
11175                         GL_DepthMask(true);
11176                 }
11177                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11178                 {
11179                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11180                                 continue;
11181                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11182                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11183                         {
11184                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11185                                 qglBegin(GL_LINES);
11186                                 if (r_shownormals.value < 0)
11187                                 {
11188                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11189                                         {
11190                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11191                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11192                                                 qglVertex3f(v[0], v[1], v[2]);
11193                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11194                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11195                                                 qglVertex3f(v[0], v[1], v[2]);
11196                                         }
11197                                 }
11198                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11199                                 {
11200                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11201                                         {
11202                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11203                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11204                                                 qglVertex3f(v[0], v[1], v[2]);
11205                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11206                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11207                                                 qglVertex3f(v[0], v[1], v[2]);
11208                                         }
11209                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11210                                         {
11211                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11212                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11213                                                 qglVertex3f(v[0], v[1], v[2]);
11214                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11215                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11216                                                 qglVertex3f(v[0], v[1], v[2]);
11217                                         }
11218                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11219                                         {
11220                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11221                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11222                                                 qglVertex3f(v[0], v[1], v[2]);
11223                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11224                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11225                                                 qglVertex3f(v[0], v[1], v[2]);
11226                                         }
11227                                 }
11228                                 qglEnd();
11229                                 CHECKGLERROR
11230                         }
11231                 }
11232                 rsurface.texture = NULL;
11233         }
11234 }
11235
11236 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11237 int r_maxsurfacelist = 0;
11238 const msurface_t **r_surfacelist = NULL;
11239 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11240 {
11241         int i, j, endj, flagsmask;
11242         dp_model_t *model = r_refdef.scene.worldmodel;
11243         msurface_t *surfaces;
11244         unsigned char *update;
11245         int numsurfacelist = 0;
11246         if (model == NULL)
11247                 return;
11248
11249         if (r_maxsurfacelist < model->num_surfaces)
11250         {
11251                 r_maxsurfacelist = model->num_surfaces;
11252                 if (r_surfacelist)
11253                         Mem_Free((msurface_t**)r_surfacelist);
11254                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11255         }
11256
11257         RSurf_ActiveWorldEntity();
11258
11259         surfaces = model->data_surfaces;
11260         update = model->brushq1.lightmapupdateflags;
11261
11262         // update light styles on this submodel
11263         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11264         {
11265                 model_brush_lightstyleinfo_t *style;
11266                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11267                 {
11268                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11269                         {
11270                                 int *list = style->surfacelist;
11271                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11272                                 for (j = 0;j < style->numsurfaces;j++)
11273                                         update[list[j]] = true;
11274                         }
11275                 }
11276         }
11277
11278         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11279
11280         if (debug)
11281         {
11282                 R_DrawDebugModel();
11283                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11284                 return;
11285         }
11286
11287         rsurface.lightmaptexture = NULL;
11288         rsurface.deluxemaptexture = NULL;
11289         rsurface.uselightmaptexture = false;
11290         rsurface.texture = NULL;
11291         rsurface.rtlight = NULL;
11292         numsurfacelist = 0;
11293         // add visible surfaces to draw list
11294         for (i = 0;i < model->nummodelsurfaces;i++)
11295         {
11296                 j = model->sortedmodelsurfaces[i];
11297                 if (r_refdef.viewcache.world_surfacevisible[j])
11298                         r_surfacelist[numsurfacelist++] = surfaces + j;
11299         }
11300         // update lightmaps if needed
11301         if (model->brushq1.firstrender)
11302         {
11303                 model->brushq1.firstrender = false;
11304                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11305                         if (update[j])
11306                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11307         }
11308         else if (update)
11309         {
11310                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11311                         if (r_refdef.viewcache.world_surfacevisible[j])
11312                                 if (update[j])
11313                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11314         }
11315         // don't do anything if there were no surfaces
11316         if (!numsurfacelist)
11317         {
11318                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11319                 return;
11320         }
11321         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11322
11323         // add to stats if desired
11324         if (r_speeds.integer && !skysurfaces && !depthonly)
11325         {
11326                 r_refdef.stats.world_surfaces += numsurfacelist;
11327                 for (j = 0;j < numsurfacelist;j++)
11328                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11329         }
11330
11331         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11332 }
11333
11334 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11335 {
11336         int i, j, endj, flagsmask;
11337         dp_model_t *model = ent->model;
11338         msurface_t *surfaces;
11339         unsigned char *update;
11340         int numsurfacelist = 0;
11341         if (model == NULL)
11342                 return;
11343
11344         if (r_maxsurfacelist < model->num_surfaces)
11345         {
11346                 r_maxsurfacelist = model->num_surfaces;
11347                 if (r_surfacelist)
11348                         Mem_Free((msurface_t **)r_surfacelist);
11349                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11350         }
11351
11352         // if the model is static it doesn't matter what value we give for
11353         // wantnormals and wanttangents, so this logic uses only rules applicable
11354         // to a model, knowing that they are meaningless otherwise
11355         if (ent == r_refdef.scene.worldentity)
11356                 RSurf_ActiveWorldEntity();
11357         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11358                 RSurf_ActiveModelEntity(ent, false, false, false);
11359         else if (prepass)
11360                 RSurf_ActiveModelEntity(ent, true, true, true);
11361         else if (depthonly)
11362         {
11363                 switch (vid.renderpath)
11364                 {
11365                 case RENDERPATH_GL20:
11366                 case RENDERPATH_D3D9:
11367                 case RENDERPATH_D3D10:
11368                 case RENDERPATH_D3D11:
11369                 case RENDERPATH_SOFT:
11370                 case RENDERPATH_GLES2:
11371                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11372                         break;
11373                 case RENDERPATH_GL11:
11374                 case RENDERPATH_GL13:
11375                 case RENDERPATH_GLES1:
11376                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11377                         break;
11378                 }
11379         }
11380         else
11381         {
11382                 switch (vid.renderpath)
11383                 {
11384                 case RENDERPATH_GL20:
11385                 case RENDERPATH_D3D9:
11386                 case RENDERPATH_D3D10:
11387                 case RENDERPATH_D3D11:
11388                 case RENDERPATH_SOFT:
11389                 case RENDERPATH_GLES2:
11390                         RSurf_ActiveModelEntity(ent, true, true, false);
11391                         break;
11392                 case RENDERPATH_GL11:
11393                 case RENDERPATH_GL13:
11394                 case RENDERPATH_GLES1:
11395                         RSurf_ActiveModelEntity(ent, true, false, false);
11396                         break;
11397                 }
11398         }
11399
11400         surfaces = model->data_surfaces;
11401         update = model->brushq1.lightmapupdateflags;
11402
11403         // update light styles
11404         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11405         {
11406                 model_brush_lightstyleinfo_t *style;
11407                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11408                 {
11409                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11410                         {
11411                                 int *list = style->surfacelist;
11412                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11413                                 for (j = 0;j < style->numsurfaces;j++)
11414                                         update[list[j]] = true;
11415                         }
11416                 }
11417         }
11418
11419         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11420
11421         if (debug)
11422         {
11423                 R_DrawDebugModel();
11424                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11425                 return;
11426         }
11427
11428         rsurface.lightmaptexture = NULL;
11429         rsurface.deluxemaptexture = NULL;
11430         rsurface.uselightmaptexture = false;
11431         rsurface.texture = NULL;
11432         rsurface.rtlight = NULL;
11433         numsurfacelist = 0;
11434         // add visible surfaces to draw list
11435         for (i = 0;i < model->nummodelsurfaces;i++)
11436                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11437         // don't do anything if there were no surfaces
11438         if (!numsurfacelist)
11439         {
11440                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11441                 return;
11442         }
11443         // update lightmaps if needed
11444         if (update)
11445         {
11446                 int updated = 0;
11447                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11448                 {
11449                         if (update[j])
11450                         {
11451                                 updated++;
11452                                 R_BuildLightMap(ent, surfaces + j);
11453                         }
11454                 }
11455         }
11456         if (update)
11457                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11458                         if (update[j])
11459                                 R_BuildLightMap(ent, surfaces + j);
11460         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11461
11462         // add to stats if desired
11463         if (r_speeds.integer && !skysurfaces && !depthonly)
11464         {
11465                 r_refdef.stats.entities_surfaces += numsurfacelist;
11466                 for (j = 0;j < numsurfacelist;j++)
11467                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11468         }
11469
11470         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11471 }
11472
11473 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11474 {
11475         static texture_t texture;
11476         static msurface_t surface;
11477         const msurface_t *surfacelist = &surface;
11478
11479         // fake enough texture and surface state to render this geometry
11480
11481         texture.update_lastrenderframe = -1; // regenerate this texture
11482         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11483         texture.currentskinframe = skinframe;
11484         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11485         texture.offsetmapping = OFFSETMAPPING_OFF;
11486         texture.offsetscale = 1;
11487         texture.specularscalemod = 1;
11488         texture.specularpowermod = 1;
11489
11490         surface.texture = &texture;
11491         surface.num_triangles = numtriangles;
11492         surface.num_firsttriangle = firsttriangle;
11493         surface.num_vertices = numvertices;
11494         surface.num_firstvertex = firstvertex;
11495
11496         // now render it
11497         rsurface.texture = R_GetCurrentTexture(surface.texture);
11498         rsurface.lightmaptexture = NULL;
11499         rsurface.deluxemaptexture = NULL;
11500         rsurface.uselightmaptexture = false;
11501         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11502 }
11503
11504 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)
11505 {
11506         static msurface_t surface;
11507         const msurface_t *surfacelist = &surface;
11508
11509         // fake enough texture and surface state to render this geometry
11510         surface.texture = texture;
11511         surface.num_triangles = numtriangles;
11512         surface.num_firsttriangle = firsttriangle;
11513         surface.num_vertices = numvertices;
11514         surface.num_firstvertex = firstvertex;
11515
11516         // now render it
11517         rsurface.texture = R_GetCurrentTexture(surface.texture);
11518         rsurface.lightmaptexture = NULL;
11519         rsurface.deluxemaptexture = NULL;
11520         rsurface.uselightmaptexture = false;
11521         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11522 }