]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
9b973e5748f7793eeb9d05cf4bd7ad2eccc93e34
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 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"};
120
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
129
130 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)"};
131 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"};
132
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
138
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142
143 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)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 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)"};
149 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)"};
150 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)"};
151 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)"};
152 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)"};
153 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)"};
154 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)"};
155 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)"};
156
157 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)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 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"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
163
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
168
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
176
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 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)"};
181 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
182 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
183 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
184 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
185 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
186 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
187
188 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"};
189
190 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"};
191
192 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
193
194 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
195 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"};
196 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
197 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
198 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
199 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
200 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)"};
201 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
202 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
203
204 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
205 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"};
206
207 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)"};
208
209 extern cvar_t v_glslgamma;
210
211 extern qboolean v_flipped_state;
212
213 static struct r_bloomstate_s
214 {
215         qboolean enabled;
216         qboolean hdr;
217
218         int bloomwidth, bloomheight;
219
220         int screentexturewidth, screentextureheight;
221         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
222
223         int bloomtexturewidth, bloomtextureheight;
224         rtexture_t *texture_bloom;
225
226         // arrays for rendering the screen passes
227         float screentexcoord2f[8];
228         float bloomtexcoord2f[8];
229         float offsettexcoord2f[8];
230
231         r_viewport_t viewport;
232 }
233 r_bloomstate;
234
235 r_waterstate_t r_waterstate;
236
237 /// shadow volume bsp struct with automatically growing nodes buffer
238 svbsp_t r_svbsp;
239
240 rtexture_t *r_texture_blanknormalmap;
241 rtexture_t *r_texture_white;
242 rtexture_t *r_texture_grey128;
243 rtexture_t *r_texture_black;
244 rtexture_t *r_texture_notexture;
245 rtexture_t *r_texture_whitecube;
246 rtexture_t *r_texture_normalizationcube;
247 rtexture_t *r_texture_fogattenuation;
248 rtexture_t *r_texture_fogheighttexture;
249 rtexture_t *r_texture_gammaramps;
250 unsigned int r_texture_gammaramps_serial;
251 //rtexture_t *r_texture_fogintensity;
252 rtexture_t *r_texture_reflectcube;
253
254 // TODO: hash lookups?
255 typedef struct cubemapinfo_s
256 {
257         char basename[64];
258         rtexture_t *texture;
259 }
260 cubemapinfo_t;
261
262 int r_texture_numcubemaps;
263 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
264
265 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
266 unsigned int r_numqueries;
267 unsigned int r_maxqueries;
268
269 typedef struct r_qwskincache_s
270 {
271         char name[MAX_QPATH];
272         skinframe_t *skinframe;
273 }
274 r_qwskincache_t;
275
276 static r_qwskincache_t *r_qwskincache;
277 static int r_qwskincache_size;
278
279 /// vertex coordinates for a quad that covers the screen exactly
280 extern const float r_screenvertex3f[12];
281 extern const float r_d3dscreenvertex3f[12];
282 const float r_screenvertex3f[12] =
283 {
284         0, 0, 0,
285         1, 0, 0,
286         1, 1, 0,
287         0, 1, 0
288 };
289 const float r_d3dscreenvertex3f[12] =
290 {
291         0, 1, 0,
292         1, 1, 0,
293         1, 0, 0,
294         0, 0, 0
295 };
296
297 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
298 {
299         int i;
300         for (i = 0;i < verts;i++)
301         {
302                 out[0] = in[0] * r;
303                 out[1] = in[1] * g;
304                 out[2] = in[2] * b;
305                 out[3] = in[3];
306                 in += 4;
307                 out += 4;
308         }
309 }
310
311 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
312 {
313         int i;
314         for (i = 0;i < verts;i++)
315         {
316                 out[0] = r;
317                 out[1] = g;
318                 out[2] = b;
319                 out[3] = a;
320                 out += 4;
321         }
322 }
323
324 // FIXME: move this to client?
325 void FOG_clear(void)
326 {
327         if (gamemode == GAME_NEHAHRA)
328         {
329                 Cvar_Set("gl_fogenable", "0");
330                 Cvar_Set("gl_fogdensity", "0.2");
331                 Cvar_Set("gl_fogred", "0.3");
332                 Cvar_Set("gl_foggreen", "0.3");
333                 Cvar_Set("gl_fogblue", "0.3");
334         }
335         r_refdef.fog_density = 0;
336         r_refdef.fog_red = 0;
337         r_refdef.fog_green = 0;
338         r_refdef.fog_blue = 0;
339         r_refdef.fog_alpha = 1;
340         r_refdef.fog_start = 0;
341         r_refdef.fog_end = 16384;
342         r_refdef.fog_height = 1<<30;
343         r_refdef.fog_fadedepth = 128;
344         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
345 }
346
347 static void R_BuildBlankTextures(void)
348 {
349         unsigned char data[4];
350         data[2] = 128; // normal X
351         data[1] = 128; // normal Y
352         data[0] = 255; // normal Z
353         data[3] = 128; // height
354         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
355         data[0] = 255;
356         data[1] = 255;
357         data[2] = 255;
358         data[3] = 255;
359         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
360         data[0] = 128;
361         data[1] = 128;
362         data[2] = 128;
363         data[3] = 255;
364         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365         data[0] = 0;
366         data[1] = 0;
367         data[2] = 0;
368         data[3] = 255;
369         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370 }
371
372 static void R_BuildNoTexture(void)
373 {
374         int x, y;
375         unsigned char pix[16][16][4];
376         // this makes a light grey/dark grey checkerboard texture
377         for (y = 0;y < 16;y++)
378         {
379                 for (x = 0;x < 16;x++)
380                 {
381                         if ((y < 8) ^ (x < 8))
382                         {
383                                 pix[y][x][0] = 128;
384                                 pix[y][x][1] = 128;
385                                 pix[y][x][2] = 128;
386                                 pix[y][x][3] = 255;
387                         }
388                         else
389                         {
390                                 pix[y][x][0] = 64;
391                                 pix[y][x][1] = 64;
392                                 pix[y][x][2] = 64;
393                                 pix[y][x][3] = 255;
394                         }
395                 }
396         }
397         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
398 }
399
400 static void R_BuildWhiteCube(void)
401 {
402         unsigned char data[6*1*1*4];
403         memset(data, 255, sizeof(data));
404         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
405 }
406
407 static void R_BuildNormalizationCube(void)
408 {
409         int x, y, side;
410         vec3_t v;
411         vec_t s, t, intensity;
412 #define NORMSIZE 64
413         unsigned char *data;
414         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
415         for (side = 0;side < 6;side++)
416         {
417                 for (y = 0;y < NORMSIZE;y++)
418                 {
419                         for (x = 0;x < NORMSIZE;x++)
420                         {
421                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
422                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
423                                 switch(side)
424                                 {
425                                 default:
426                                 case 0:
427                                         v[0] = 1;
428                                         v[1] = -t;
429                                         v[2] = -s;
430                                         break;
431                                 case 1:
432                                         v[0] = -1;
433                                         v[1] = -t;
434                                         v[2] = s;
435                                         break;
436                                 case 2:
437                                         v[0] = s;
438                                         v[1] = 1;
439                                         v[2] = t;
440                                         break;
441                                 case 3:
442                                         v[0] = s;
443                                         v[1] = -1;
444                                         v[2] = -t;
445                                         break;
446                                 case 4:
447                                         v[0] = s;
448                                         v[1] = -t;
449                                         v[2] = 1;
450                                         break;
451                                 case 5:
452                                         v[0] = -s;
453                                         v[1] = -t;
454                                         v[2] = -1;
455                                         break;
456                                 }
457                                 intensity = 127.0f / sqrt(DotProduct(v, v));
458                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
459                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
460                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
461                                 data[((side*64+y)*64+x)*4+3] = 255;
462                         }
463                 }
464         }
465         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
466         Mem_Free(data);
467 }
468
469 static void R_BuildFogTexture(void)
470 {
471         int x, b;
472 #define FOGWIDTH 256
473         unsigned char data1[FOGWIDTH][4];
474         //unsigned char data2[FOGWIDTH][4];
475         double d, r, alpha;
476
477         r_refdef.fogmasktable_start = r_refdef.fog_start;
478         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
479         r_refdef.fogmasktable_range = r_refdef.fogrange;
480         r_refdef.fogmasktable_density = r_refdef.fog_density;
481
482         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
483         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
484         {
485                 d = (x * r - r_refdef.fogmasktable_start);
486                 if(developer_extra.integer)
487                         Con_DPrintf("%f ", d);
488                 d = max(0, d);
489                 if (r_fog_exp2.integer)
490                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
491                 else
492                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
493                 if(developer_extra.integer)
494                         Con_DPrintf(" : %f ", alpha);
495                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
496                 if(developer_extra.integer)
497                         Con_DPrintf(" = %f\n", alpha);
498                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
499         }
500
501         for (x = 0;x < FOGWIDTH;x++)
502         {
503                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
504                 data1[x][0] = b;
505                 data1[x][1] = b;
506                 data1[x][2] = b;
507                 data1[x][3] = 255;
508                 //data2[x][0] = 255 - b;
509                 //data2[x][1] = 255 - b;
510                 //data2[x][2] = 255 - b;
511                 //data2[x][3] = 255;
512         }
513         if (r_texture_fogattenuation)
514         {
515                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
516                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
517         }
518         else
519         {
520                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
521                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
522         }
523 }
524
525 static void R_BuildFogHeightTexture(void)
526 {
527         unsigned char *inpixels;
528         int size;
529         int x;
530         int y;
531         int j;
532         float c[4];
533         float f;
534         inpixels = NULL;
535         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
536         if (r_refdef.fogheighttexturename[0])
537                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
538         if (!inpixels)
539         {
540                 r_refdef.fog_height_tablesize = 0;
541                 if (r_texture_fogheighttexture)
542                         R_FreeTexture(r_texture_fogheighttexture);
543                 r_texture_fogheighttexture = NULL;
544                 if (r_refdef.fog_height_table2d)
545                         Mem_Free(r_refdef.fog_height_table2d);
546                 r_refdef.fog_height_table2d = NULL;
547                 if (r_refdef.fog_height_table1d)
548                         Mem_Free(r_refdef.fog_height_table1d);
549                 r_refdef.fog_height_table1d = NULL;
550                 return;
551         }
552         size = image_width;
553         r_refdef.fog_height_tablesize = size;
554         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
555         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
556         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
557         Mem_Free(inpixels);
558         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
559         // average fog color table accounting for every fog layer between a point
560         // and the camera.  (Note: attenuation is handled separately!)
561         for (y = 0;y < size;y++)
562         {
563                 for (x = 0;x < size;x++)
564                 {
565                         Vector4Clear(c);
566                         f = 0;
567                         if (x < y)
568                         {
569                                 for (j = x;j <= y;j++)
570                                 {
571                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
572                                         f++;
573                                 }
574                         }
575                         else
576                         {
577                                 for (j = x;j >= y;j--)
578                                 {
579                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
580                                         f++;
581                                 }
582                         }
583                         f = 1.0f / f;
584                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
585                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
586                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
587                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
588                 }
589         }
590         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
591 }
592
593 //=======================================================================================================================================================
594
595 static const char *builtinshaderstring =
596 #include "shader_glsl.h"
597 ;
598
599 const char *builtinhlslshaderstring =
600 #include "shader_hlsl.h"
601 ;
602
603 char *glslshaderstring = NULL;
604 char *hlslshaderstring = NULL;
605
606 //=======================================================================================================================================================
607
608 typedef struct shaderpermutationinfo_s
609 {
610         const char *pretext;
611         const char *name;
612 }
613 shaderpermutationinfo_t;
614
615 typedef struct shadermodeinfo_s
616 {
617         const char *vertexfilename;
618         const char *geometryfilename;
619         const char *fragmentfilename;
620         const char *pretext;
621         const char *name;
622 }
623 shadermodeinfo_t;
624
625 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
626 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
627 {
628         {"#define USEDIFFUSE\n", " diffuse"},
629         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
630         {"#define USEVIEWTINT\n", " viewtint"},
631         {"#define USECOLORMAPPING\n", " colormapping"},
632         {"#define USESATURATION\n", " saturation"},
633         {"#define USEFOGINSIDE\n", " foginside"},
634         {"#define USEFOGOUTSIDE\n", " fogoutside"},
635         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
636         {"#define USEGAMMARAMPS\n", " gammaramps"},
637         {"#define USECUBEFILTER\n", " cubefilter"},
638         {"#define USEGLOW\n", " glow"},
639         {"#define USEBLOOM\n", " bloom"},
640         {"#define USESPECULAR\n", " specular"},
641         {"#define USEPOSTPROCESSING\n", " postprocessing"},
642         {"#define USEREFLECTION\n", " reflection"},
643         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
644         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
645         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
646         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
647         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
648         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
649         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
650         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
651         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
652         {"#define USEALPHAKILL\n", " alphakill"},
653         {"#define USEREFLECTCUBE\n", " reflectcube"},
654         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
655         {"#define USEBOUNCEGRID\n", " bouncegrid"},
656 };
657
658 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
659 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
660 {
661         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
662         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
663         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
677 };
678
679 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
680 {
681         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
682         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
683         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
697 };
698
699 struct r_glsl_permutation_s;
700 typedef struct r_glsl_permutation_s
701 {
702         /// hash lookup data
703         struct r_glsl_permutation_s *hashnext;
704         unsigned int mode;
705         unsigned int permutation;
706
707         /// indicates if we have tried compiling this permutation already
708         qboolean compiled;
709         /// 0 if compilation failed
710         int program;
711         // texture units assigned to each detected uniform
712         int tex_Texture_First;
713         int tex_Texture_Second;
714         int tex_Texture_GammaRamps;
715         int tex_Texture_Normal;
716         int tex_Texture_Color;
717         int tex_Texture_Gloss;
718         int tex_Texture_Glow;
719         int tex_Texture_SecondaryNormal;
720         int tex_Texture_SecondaryColor;
721         int tex_Texture_SecondaryGloss;
722         int tex_Texture_SecondaryGlow;
723         int tex_Texture_Pants;
724         int tex_Texture_Shirt;
725         int tex_Texture_FogHeightTexture;
726         int tex_Texture_FogMask;
727         int tex_Texture_Lightmap;
728         int tex_Texture_Deluxemap;
729         int tex_Texture_Attenuation;
730         int tex_Texture_Cube;
731         int tex_Texture_Refraction;
732         int tex_Texture_Reflection;
733         int tex_Texture_ShadowMap2D;
734         int tex_Texture_CubeProjection;
735         int tex_Texture_ScreenDepth;
736         int tex_Texture_ScreenNormalMap;
737         int tex_Texture_ScreenDiffuse;
738         int tex_Texture_ScreenSpecular;
739         int tex_Texture_ReflectMask;
740         int tex_Texture_ReflectCube;
741         int tex_Texture_BounceGrid;
742         /// locations of detected uniforms in program object, or -1 if not found
743         int loc_Texture_First;
744         int loc_Texture_Second;
745         int loc_Texture_GammaRamps;
746         int loc_Texture_Normal;
747         int loc_Texture_Color;
748         int loc_Texture_Gloss;
749         int loc_Texture_Glow;
750         int loc_Texture_SecondaryNormal;
751         int loc_Texture_SecondaryColor;
752         int loc_Texture_SecondaryGloss;
753         int loc_Texture_SecondaryGlow;
754         int loc_Texture_Pants;
755         int loc_Texture_Shirt;
756         int loc_Texture_FogHeightTexture;
757         int loc_Texture_FogMask;
758         int loc_Texture_Lightmap;
759         int loc_Texture_Deluxemap;
760         int loc_Texture_Attenuation;
761         int loc_Texture_Cube;
762         int loc_Texture_Refraction;
763         int loc_Texture_Reflection;
764         int loc_Texture_ShadowMap2D;
765         int loc_Texture_CubeProjection;
766         int loc_Texture_ScreenDepth;
767         int loc_Texture_ScreenNormalMap;
768         int loc_Texture_ScreenDiffuse;
769         int loc_Texture_ScreenSpecular;
770         int loc_Texture_ReflectMask;
771         int loc_Texture_ReflectCube;
772         int loc_Texture_BounceGrid;
773         int loc_Alpha;
774         int loc_BloomBlur_Parameters;
775         int loc_ClientTime;
776         int loc_Color_Ambient;
777         int loc_Color_Diffuse;
778         int loc_Color_Specular;
779         int loc_Color_Glow;
780         int loc_Color_Pants;
781         int loc_Color_Shirt;
782         int loc_DeferredColor_Ambient;
783         int loc_DeferredColor_Diffuse;
784         int loc_DeferredColor_Specular;
785         int loc_DeferredMod_Diffuse;
786         int loc_DeferredMod_Specular;
787         int loc_DistortScaleRefractReflect;
788         int loc_EyePosition;
789         int loc_FogColor;
790         int loc_FogHeightFade;
791         int loc_FogPlane;
792         int loc_FogPlaneViewDist;
793         int loc_FogRangeRecip;
794         int loc_LightColor;
795         int loc_LightDir;
796         int loc_LightPosition;
797         int loc_OffsetMapping_Scale;
798         int loc_PixelSize;
799         int loc_ReflectColor;
800         int loc_ReflectFactor;
801         int loc_ReflectOffset;
802         int loc_RefractColor;
803         int loc_Saturation;
804         int loc_ScreenCenterRefractReflect;
805         int loc_ScreenScaleRefractReflect;
806         int loc_ScreenToDepth;
807         int loc_ShadowMap_Parameters;
808         int loc_ShadowMap_TextureScale;
809         int loc_SpecularPower;
810         int loc_UserVec1;
811         int loc_UserVec2;
812         int loc_UserVec3;
813         int loc_UserVec4;
814         int loc_ViewTintColor;
815         int loc_ViewToLight;
816         int loc_ModelToLight;
817         int loc_TexMatrix;
818         int loc_BackgroundTexMatrix;
819         int loc_ModelViewProjectionMatrix;
820         int loc_ModelViewMatrix;
821         int loc_PixelToScreenTexCoord;
822         int loc_ModelToReflectCube;
823         int loc_ShadowMapMatrix;
824         int loc_BloomColorSubtract;
825         int loc_NormalmapScrollBlend;
826         int loc_BounceGridMatrix;
827         int loc_BounceGridIntensity;
828 }
829 r_glsl_permutation_t;
830
831 #define SHADERPERMUTATION_HASHSIZE 256
832
833
834 // non-degradable "lightweight" shader parameters to keep the permutations simpler
835 // these can NOT degrade! only use for simple stuff
836 enum
837 {
838         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
839         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
840         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
841         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
842         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
843         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
844 };
845 #define SHADERSTATICPARMS_COUNT 6
846
847 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
848 static int shaderstaticparms_count = 0;
849
850 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
851 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
852 qboolean R_CompileShader_CheckStaticParms(void)
853 {
854         static int r_compileshader_staticparms_save[1];
855         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
856         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
857
858         // detect all
859         if (r_glsl_saturation_redcompensate.integer)
860                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
861         if (r_shadow_glossexact.integer)
862                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
863         if (r_glsl_postprocess.integer)
864         {
865                 if (r_glsl_postprocess_uservec1_enable.integer)
866                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
867                 if (r_glsl_postprocess_uservec2_enable.integer)
868                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
869                 if (r_glsl_postprocess_uservec3_enable.integer)
870                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
871                 if (r_glsl_postprocess_uservec4_enable.integer)
872                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
873         }
874         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
875 }
876
877 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
878         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
879                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
880         else \
881                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
882 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
883 {
884         shaderstaticparms_count = 0;
885
886         // emit all
887         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
888         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
889         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
890         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
891         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
892         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
893 }
894
895 /// information about each possible shader permutation
896 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
897 /// currently selected permutation
898 r_glsl_permutation_t *r_glsl_permutation;
899 /// storage for permutations linked in the hash table
900 memexpandablearray_t r_glsl_permutationarray;
901
902 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
903 {
904         //unsigned int hashdepth = 0;
905         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
906         r_glsl_permutation_t *p;
907         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
908         {
909                 if (p->mode == mode && p->permutation == permutation)
910                 {
911                         //if (hashdepth > 10)
912                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
913                         return p;
914                 }
915                 //hashdepth++;
916         }
917         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
918         p->mode = mode;
919         p->permutation = permutation;
920         p->hashnext = r_glsl_permutationhash[mode][hashindex];
921         r_glsl_permutationhash[mode][hashindex] = p;
922         //if (hashdepth > 10)
923         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
924         return p;
925 }
926
927 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
928 {
929         char *shaderstring;
930         if (!filename || !filename[0])
931                 return NULL;
932         if (!strcmp(filename, "glsl/default.glsl"))
933         {
934                 if (!glslshaderstring)
935                 {
936                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
937                         if (glslshaderstring)
938                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
939                         else
940                                 glslshaderstring = (char *)builtinshaderstring;
941                 }
942                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
943                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
944                 return shaderstring;
945         }
946         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
947         if (shaderstring)
948         {
949                 if (printfromdisknotice)
950                         Con_DPrintf("from disk %s... ", filename);
951                 return shaderstring;
952         }
953         return shaderstring;
954 }
955
956 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
957 {
958         int i;
959         int sampler;
960         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
961         char *vertexstring, *geometrystring, *fragmentstring;
962         char permutationname[256];
963         int vertstrings_count = 0;
964         int geomstrings_count = 0;
965         int fragstrings_count = 0;
966         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
967         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
968         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
969
970         if (p->compiled)
971                 return;
972         p->compiled = true;
973         p->program = 0;
974
975         permutationname[0] = 0;
976         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
977         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
978         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
979
980         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
981
982         // the first pretext is which type of shader to compile as
983         // (later these will all be bound together as a program object)
984         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
985         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
986         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
987
988         // the second pretext is the mode (for example a light source)
989         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
990         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
991         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
992         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
993
994         // now add all the permutation pretexts
995         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
996         {
997                 if (permutation & (1<<i))
998                 {
999                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1000                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1001                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1002                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1003                 }
1004                 else
1005                 {
1006                         // keep line numbers correct
1007                         vertstrings_list[vertstrings_count++] = "\n";
1008                         geomstrings_list[geomstrings_count++] = "\n";
1009                         fragstrings_list[fragstrings_count++] = "\n";
1010                 }
1011         }
1012
1013         // add static parms
1014         R_CompileShader_AddStaticParms(mode, permutation);
1015         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1016         vertstrings_count += shaderstaticparms_count;
1017         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1018         geomstrings_count += shaderstaticparms_count;
1019         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1020         fragstrings_count += shaderstaticparms_count;
1021
1022         // now append the shader text itself
1023         vertstrings_list[vertstrings_count++] = vertexstring;
1024         geomstrings_list[geomstrings_count++] = geometrystring;
1025         fragstrings_list[fragstrings_count++] = fragmentstring;
1026
1027         // if any sources were NULL, clear the respective list
1028         if (!vertexstring)
1029                 vertstrings_count = 0;
1030         if (!geometrystring)
1031                 geomstrings_count = 0;
1032         if (!fragmentstring)
1033                 fragstrings_count = 0;
1034
1035         // compile the shader program
1036         if (vertstrings_count + geomstrings_count + fragstrings_count)
1037                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1038         if (p->program)
1039         {
1040                 CHECKGLERROR
1041                 qglUseProgram(p->program);CHECKGLERROR
1042                 // look up all the uniform variable names we care about, so we don't
1043                 // have to look them up every time we set them
1044
1045                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1046                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1047                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1048                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1049                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1050                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1051                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1052                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1053                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1054                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1055                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1056                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1057                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1058                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1059                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1060                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1061                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1062                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1063                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1064                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1065                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1066                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1067                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1068                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1069                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1070                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1071                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1072                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1073                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1074                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1075                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1076                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1077                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1078                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1079                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1080                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1081                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1082                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1083                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1084                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1085                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1086                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1087                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1088                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1089                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1090                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1091                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1092                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1093                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1094                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1095                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1096                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1097                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1098                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1099                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
1100                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1101                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1102                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1103                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1104                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1105                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1106                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1107                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1108                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1109                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1110                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1111                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1112                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1113                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1114                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1115                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1116                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1117                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1118                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1119                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1120                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1121                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1122                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1123                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1124                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1125                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1126                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1127                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1128                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1129                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1130                 // initialize the samplers to refer to the texture units we use
1131                 p->tex_Texture_First = -1;
1132                 p->tex_Texture_Second = -1;
1133                 p->tex_Texture_GammaRamps = -1;
1134                 p->tex_Texture_Normal = -1;
1135                 p->tex_Texture_Color = -1;
1136                 p->tex_Texture_Gloss = -1;
1137                 p->tex_Texture_Glow = -1;
1138                 p->tex_Texture_SecondaryNormal = -1;
1139                 p->tex_Texture_SecondaryColor = -1;
1140                 p->tex_Texture_SecondaryGloss = -1;
1141                 p->tex_Texture_SecondaryGlow = -1;
1142                 p->tex_Texture_Pants = -1;
1143                 p->tex_Texture_Shirt = -1;
1144                 p->tex_Texture_FogHeightTexture = -1;
1145                 p->tex_Texture_FogMask = -1;
1146                 p->tex_Texture_Lightmap = -1;
1147                 p->tex_Texture_Deluxemap = -1;
1148                 p->tex_Texture_Attenuation = -1;
1149                 p->tex_Texture_Cube = -1;
1150                 p->tex_Texture_Refraction = -1;
1151                 p->tex_Texture_Reflection = -1;
1152                 p->tex_Texture_ShadowMap2D = -1;
1153                 p->tex_Texture_CubeProjection = -1;
1154                 p->tex_Texture_ScreenDepth = -1;
1155                 p->tex_Texture_ScreenNormalMap = -1;
1156                 p->tex_Texture_ScreenDiffuse = -1;
1157                 p->tex_Texture_ScreenSpecular = -1;
1158                 p->tex_Texture_ReflectMask = -1;
1159                 p->tex_Texture_ReflectCube = -1;
1160                 p->tex_Texture_BounceGrid = -1;
1161                 sampler = 0;
1162                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1163                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1164                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1165                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1166                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1167                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1168                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1169                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1170                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1171                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1172                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1173                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1174                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1175                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1176                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1177                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1178                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1179                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1180                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1181                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1182                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1183                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1184                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1185                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1186                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1187                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1188                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1189                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1190                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1191                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1192                 CHECKGLERROR
1193                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1194         }
1195         else
1196                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1197
1198         // free the strings
1199         if (vertexstring)
1200                 Mem_Free(vertexstring);
1201         if (geometrystring)
1202                 Mem_Free(geometrystring);
1203         if (fragmentstring)
1204                 Mem_Free(fragmentstring);
1205 }
1206
1207 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1208 {
1209         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1210         if (r_glsl_permutation != perm)
1211         {
1212                 r_glsl_permutation = perm;
1213                 if (!r_glsl_permutation->program)
1214                 {
1215                         if (!r_glsl_permutation->compiled)
1216                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1217                         if (!r_glsl_permutation->program)
1218                         {
1219                                 // remove features until we find a valid permutation
1220                                 int i;
1221                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1222                                 {
1223                                         // reduce i more quickly whenever it would not remove any bits
1224                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1225                                         if (!(permutation & j))
1226                                                 continue;
1227                                         permutation -= j;
1228                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1229                                         if (!r_glsl_permutation->compiled)
1230                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1231                                         if (r_glsl_permutation->program)
1232                                                 break;
1233                                 }
1234                                 if (i >= SHADERPERMUTATION_COUNT)
1235                                 {
1236                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1237                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1238                                         qglUseProgram(0);CHECKGLERROR
1239                                         return; // no bit left to clear, entire mode is broken
1240                                 }
1241                         }
1242                 }
1243                 CHECKGLERROR
1244                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1245         }
1246         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1247         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1248         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1249 }
1250
1251 #ifdef SUPPORTD3D
1252
1253 #ifdef SUPPORTD3D
1254 #include <d3d9.h>
1255 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1256 extern D3DCAPS9 vid_d3d9caps;
1257 #endif
1258
1259 struct r_hlsl_permutation_s;
1260 typedef struct r_hlsl_permutation_s
1261 {
1262         /// hash lookup data
1263         struct r_hlsl_permutation_s *hashnext;
1264         unsigned int mode;
1265         unsigned int permutation;
1266
1267         /// indicates if we have tried compiling this permutation already
1268         qboolean compiled;
1269         /// NULL if compilation failed
1270         IDirect3DVertexShader9 *vertexshader;
1271         IDirect3DPixelShader9 *pixelshader;
1272 }
1273 r_hlsl_permutation_t;
1274
1275 typedef enum D3DVSREGISTER_e
1276 {
1277         D3DVSREGISTER_TexMatrix = 0, // float4x4
1278         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1279         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1280         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1281         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1282         D3DVSREGISTER_ModelToLight = 20, // float4x4
1283         D3DVSREGISTER_EyePosition = 24,
1284         D3DVSREGISTER_FogPlane = 25,
1285         D3DVSREGISTER_LightDir = 26,
1286         D3DVSREGISTER_LightPosition = 27,
1287 }
1288 D3DVSREGISTER_t;
1289
1290 typedef enum D3DPSREGISTER_e
1291 {
1292         D3DPSREGISTER_Alpha = 0,
1293         D3DPSREGISTER_BloomBlur_Parameters = 1,
1294         D3DPSREGISTER_ClientTime = 2,
1295         D3DPSREGISTER_Color_Ambient = 3,
1296         D3DPSREGISTER_Color_Diffuse = 4,
1297         D3DPSREGISTER_Color_Specular = 5,
1298         D3DPSREGISTER_Color_Glow = 6,
1299         D3DPSREGISTER_Color_Pants = 7,
1300         D3DPSREGISTER_Color_Shirt = 8,
1301         D3DPSREGISTER_DeferredColor_Ambient = 9,
1302         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1303         D3DPSREGISTER_DeferredColor_Specular = 11,
1304         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1305         D3DPSREGISTER_DeferredMod_Specular = 13,
1306         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1307         D3DPSREGISTER_EyePosition = 15, // unused
1308         D3DPSREGISTER_FogColor = 16,
1309         D3DPSREGISTER_FogHeightFade = 17,
1310         D3DPSREGISTER_FogPlane = 18,
1311         D3DPSREGISTER_FogPlaneViewDist = 19,
1312         D3DPSREGISTER_FogRangeRecip = 20,
1313         D3DPSREGISTER_LightColor = 21,
1314         D3DPSREGISTER_LightDir = 22, // unused
1315         D3DPSREGISTER_LightPosition = 23,
1316         D3DPSREGISTER_OffsetMapping_Scale = 24,
1317         D3DPSREGISTER_PixelSize = 25,
1318         D3DPSREGISTER_ReflectColor = 26,
1319         D3DPSREGISTER_ReflectFactor = 27,
1320         D3DPSREGISTER_ReflectOffset = 28,
1321         D3DPSREGISTER_RefractColor = 29,
1322         D3DPSREGISTER_Saturation = 30,
1323         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1324         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1325         D3DPSREGISTER_ScreenToDepth = 33,
1326         D3DPSREGISTER_ShadowMap_Parameters = 34,
1327         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1328         D3DPSREGISTER_SpecularPower = 36,
1329         D3DPSREGISTER_UserVec1 = 37,
1330         D3DPSREGISTER_UserVec2 = 38,
1331         D3DPSREGISTER_UserVec3 = 39,
1332         D3DPSREGISTER_UserVec4 = 40,
1333         D3DPSREGISTER_ViewTintColor = 41,
1334         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1335         D3DPSREGISTER_BloomColorSubtract = 43,
1336         D3DPSREGISTER_ViewToLight = 44, // float4x4
1337         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1338         D3DPSREGISTER_NormalmapScrollBlend = 52,
1339         // next at 53
1340 }
1341 D3DPSREGISTER_t;
1342
1343 /// information about each possible shader permutation
1344 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1345 /// currently selected permutation
1346 r_hlsl_permutation_t *r_hlsl_permutation;
1347 /// storage for permutations linked in the hash table
1348 memexpandablearray_t r_hlsl_permutationarray;
1349
1350 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1351 {
1352         //unsigned int hashdepth = 0;
1353         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1354         r_hlsl_permutation_t *p;
1355         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1356         {
1357                 if (p->mode == mode && p->permutation == permutation)
1358                 {
1359                         //if (hashdepth > 10)
1360                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1361                         return p;
1362                 }
1363                 //hashdepth++;
1364         }
1365         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1366         p->mode = mode;
1367         p->permutation = permutation;
1368         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1369         r_hlsl_permutationhash[mode][hashindex] = p;
1370         //if (hashdepth > 10)
1371         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1372         return p;
1373 }
1374
1375 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1376 {
1377         char *shaderstring;
1378         if (!filename || !filename[0])
1379                 return NULL;
1380         if (!strcmp(filename, "hlsl/default.hlsl"))
1381         {
1382                 if (!hlslshaderstring)
1383                 {
1384                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1385                         if (hlslshaderstring)
1386                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1387                         else
1388                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1389                 }
1390                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1391                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1392                 return shaderstring;
1393         }
1394         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1395         if (shaderstring)
1396         {
1397                 if (printfromdisknotice)
1398                         Con_DPrintf("from disk %s... ", filename);
1399                 return shaderstring;
1400         }
1401         return shaderstring;
1402 }
1403
1404 #include <d3dx9.h>
1405 //#include <d3dx9shader.h>
1406 //#include <d3dx9mesh.h>
1407
1408 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1409 {
1410         DWORD *vsbin = NULL;
1411         DWORD *psbin = NULL;
1412         fs_offset_t vsbinsize;
1413         fs_offset_t psbinsize;
1414 //      IDirect3DVertexShader9 *vs = NULL;
1415 //      IDirect3DPixelShader9 *ps = NULL;
1416         ID3DXBuffer *vslog = NULL;
1417         ID3DXBuffer *vsbuffer = NULL;
1418         ID3DXConstantTable *vsconstanttable = NULL;
1419         ID3DXBuffer *pslog = NULL;
1420         ID3DXBuffer *psbuffer = NULL;
1421         ID3DXConstantTable *psconstanttable = NULL;
1422         int vsresult = 0;
1423         int psresult = 0;
1424         char temp[MAX_INPUTLINE];
1425         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1426         qboolean debugshader = gl_paranoid.integer != 0;
1427         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1428         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1429         if (!debugshader)
1430         {
1431                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1432                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1433         }
1434         if ((!vsbin && vertstring) || (!psbin && fragstring))
1435         {
1436                 const char* dllnames_d3dx9 [] =
1437                 {
1438                         "d3dx9_43.dll",
1439                         "d3dx9_42.dll",
1440                         "d3dx9_41.dll",
1441                         "d3dx9_40.dll",
1442                         "d3dx9_39.dll",
1443                         "d3dx9_38.dll",
1444                         "d3dx9_37.dll",
1445                         "d3dx9_36.dll",
1446                         "d3dx9_35.dll",
1447                         "d3dx9_34.dll",
1448                         "d3dx9_33.dll",
1449                         "d3dx9_32.dll",
1450                         "d3dx9_31.dll",
1451                         "d3dx9_30.dll",
1452                         "d3dx9_29.dll",
1453                         "d3dx9_28.dll",
1454                         "d3dx9_27.dll",
1455                         "d3dx9_26.dll",
1456                         "d3dx9_25.dll",
1457                         "d3dx9_24.dll",
1458                         NULL
1459                 };
1460                 dllhandle_t d3dx9_dll = NULL;
1461                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1462                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1463                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1464                 dllfunction_t d3dx9_dllfuncs[] =
1465                 {
1466                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1467                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1468                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1469                         {NULL, NULL}
1470                 };
1471                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1472                 {
1473                         DWORD shaderflags = 0;
1474                         if (debugshader)
1475                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1476                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1477                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1478                         if (vertstring && vertstring[0])
1479                         {
1480                                 if (debugshader)
1481                                 {
1482 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1483 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1484                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1485                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1486                                 }
1487                                 else
1488                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1489                                 if (vsbuffer)
1490                                 {
1491                                         vsbinsize = vsbuffer->GetBufferSize();
1492                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1493                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1494                                         vsbuffer->Release();
1495                                 }
1496                                 if (vslog)
1497                                 {
1498                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1499                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1500                                         vslog->Release();
1501                                 }
1502                         }
1503                         if (fragstring && fragstring[0])
1504                         {
1505                                 if (debugshader)
1506                                 {
1507 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1508 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1509                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1510                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1511                                 }
1512                                 else
1513                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1514                                 if (psbuffer)
1515                                 {
1516                                         psbinsize = psbuffer->GetBufferSize();
1517                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1518                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1519                                         psbuffer->Release();
1520                                 }
1521                                 if (pslog)
1522                                 {
1523                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1524                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1525                                         pslog->Release();
1526                                 }
1527                         }
1528                         Sys_UnloadLibrary(&d3dx9_dll);
1529                 }
1530                 else
1531                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1532         }
1533         if (vsbin && psbin)
1534         {
1535                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1536                 if (FAILED(vsresult))
1537                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1538                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1539                 if (FAILED(psresult))
1540                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1541         }
1542         // free the shader data
1543         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1544         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1545 }
1546
1547 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1548 {
1549         int i;
1550         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1551         int vertstring_length = 0;
1552         int geomstring_length = 0;
1553         int fragstring_length = 0;
1554         char *t;
1555         char *vertexstring, *geometrystring, *fragmentstring;
1556         char *vertstring, *geomstring, *fragstring;
1557         char permutationname[256];
1558         char cachename[256];
1559         int vertstrings_count = 0;
1560         int geomstrings_count = 0;
1561         int fragstrings_count = 0;
1562         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1563         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1564         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1565
1566         if (p->compiled)
1567                 return;
1568         p->compiled = true;
1569         p->vertexshader = NULL;
1570         p->pixelshader = NULL;
1571
1572         permutationname[0] = 0;
1573         cachename[0] = 0;
1574         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1575         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1576         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1577
1578         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1579         strlcat(cachename, "hlsl/", sizeof(cachename));
1580
1581         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1582         vertstrings_count = 0;
1583         geomstrings_count = 0;
1584         fragstrings_count = 0;
1585         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1586         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1587         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1588
1589         // the first pretext is which type of shader to compile as
1590         // (later these will all be bound together as a program object)
1591         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1592         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1593         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1594
1595         // the second pretext is the mode (for example a light source)
1596         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1597         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1598         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1599         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1600         strlcat(cachename, modeinfo->name, sizeof(cachename));
1601
1602         // now add all the permutation pretexts
1603         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1604         {
1605                 if (permutation & (1<<i))
1606                 {
1607                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1608                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1609                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1610                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1611                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1612                 }
1613                 else
1614                 {
1615                         // keep line numbers correct
1616                         vertstrings_list[vertstrings_count++] = "\n";
1617                         geomstrings_list[geomstrings_count++] = "\n";
1618                         fragstrings_list[fragstrings_count++] = "\n";
1619                 }
1620         }
1621
1622         // add static parms
1623         R_CompileShader_AddStaticParms(mode, permutation);
1624         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1625         vertstrings_count += shaderstaticparms_count;
1626         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1627         geomstrings_count += shaderstaticparms_count;
1628         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1629         fragstrings_count += shaderstaticparms_count;
1630
1631         // replace spaces in the cachename with _ characters
1632         for (i = 0;cachename[i];i++)
1633                 if (cachename[i] == ' ')
1634                         cachename[i] = '_';
1635
1636         // now append the shader text itself
1637         vertstrings_list[vertstrings_count++] = vertexstring;
1638         geomstrings_list[geomstrings_count++] = geometrystring;
1639         fragstrings_list[fragstrings_count++] = fragmentstring;
1640
1641         // if any sources were NULL, clear the respective list
1642         if (!vertexstring)
1643                 vertstrings_count = 0;
1644         if (!geometrystring)
1645                 geomstrings_count = 0;
1646         if (!fragmentstring)
1647                 fragstrings_count = 0;
1648
1649         vertstring_length = 0;
1650         for (i = 0;i < vertstrings_count;i++)
1651                 vertstring_length += strlen(vertstrings_list[i]);
1652         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1653         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1654                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1655
1656         geomstring_length = 0;
1657         for (i = 0;i < geomstrings_count;i++)
1658                 geomstring_length += strlen(geomstrings_list[i]);
1659         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1660         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1661                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1662
1663         fragstring_length = 0;
1664         for (i = 0;i < fragstrings_count;i++)
1665                 fragstring_length += strlen(fragstrings_list[i]);
1666         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1667         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1668                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1669
1670         // try to load the cached shader, or generate one
1671         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1672
1673         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1674                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1675         else
1676                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1677
1678         // free the strings
1679         if (vertstring)
1680                 Mem_Free(vertstring);
1681         if (geomstring)
1682                 Mem_Free(geomstring);
1683         if (fragstring)
1684                 Mem_Free(fragstring);
1685         if (vertexstring)
1686                 Mem_Free(vertexstring);
1687         if (geometrystring)
1688                 Mem_Free(geometrystring);
1689         if (fragmentstring)
1690                 Mem_Free(fragmentstring);
1691 }
1692
1693 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1694 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1695 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);}
1696 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);}
1697 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);}
1698 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);}
1699
1700 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1701 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1702 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);}
1703 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);}
1704 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);}
1705 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);}
1706
1707 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1708 {
1709         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1710         if (r_hlsl_permutation != perm)
1711         {
1712                 r_hlsl_permutation = perm;
1713                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1714                 {
1715                         if (!r_hlsl_permutation->compiled)
1716                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1717                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1718                         {
1719                                 // remove features until we find a valid permutation
1720                                 int i;
1721                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1722                                 {
1723                                         // reduce i more quickly whenever it would not remove any bits
1724                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1725                                         if (!(permutation & j))
1726                                                 continue;
1727                                         permutation -= j;
1728                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1729                                         if (!r_hlsl_permutation->compiled)
1730                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1731                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1732                                                 break;
1733                                 }
1734                                 if (i >= SHADERPERMUTATION_COUNT)
1735                                 {
1736                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1737                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1738                                         return; // no bit left to clear, entire mode is broken
1739                                 }
1740                         }
1741                 }
1742                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1743                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1744         }
1745         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1746         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1747         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1748 }
1749 #endif
1750
1751 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1752 {
1753         DPSOFTRAST_SetShader(mode, permutation);
1754         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1755         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1756         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1757 }
1758
1759 void R_GLSL_Restart_f(void)
1760 {
1761         unsigned int i, limit;
1762         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1763                 Mem_Free(glslshaderstring);
1764         glslshaderstring = NULL;
1765         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1766                 Mem_Free(hlslshaderstring);
1767         hlslshaderstring = NULL;
1768         switch(vid.renderpath)
1769         {
1770         case RENDERPATH_D3D9:
1771 #ifdef SUPPORTD3D
1772                 {
1773                         r_hlsl_permutation_t *p;
1774                         r_hlsl_permutation = NULL;
1775                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1776                         for (i = 0;i < limit;i++)
1777                         {
1778                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1779                                 {
1780                                         if (p->vertexshader)
1781                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1782                                         if (p->pixelshader)
1783                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1784                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1785                                 }
1786                         }
1787                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1788                 }
1789 #endif
1790                 break;
1791         case RENDERPATH_D3D10:
1792                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1793                 break;
1794         case RENDERPATH_D3D11:
1795                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1796                 break;
1797         case RENDERPATH_GL20:
1798         case RENDERPATH_GLES2:
1799                 {
1800                         r_glsl_permutation_t *p;
1801                         r_glsl_permutation = NULL;
1802                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1803                         for (i = 0;i < limit;i++)
1804                         {
1805                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1806                                 {
1807                                         GL_Backend_FreeProgram(p->program);
1808                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1809                                 }
1810                         }
1811                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1812                 }
1813                 break;
1814         case RENDERPATH_GL13:
1815         case RENDERPATH_GL11:
1816                 break;
1817         case RENDERPATH_SOFT:
1818                 break;
1819         }
1820 }
1821
1822 void R_GLSL_DumpShader_f(void)
1823 {
1824         int i;
1825         qfile_t *file;
1826
1827         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1828         if (file)
1829         {
1830                 FS_Print(file, "/* The engine may define the following macros:\n");
1831                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1832                 for (i = 0;i < SHADERMODE_COUNT;i++)
1833                         FS_Print(file, glslshadermodeinfo[i].pretext);
1834                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1835                         FS_Print(file, shaderpermutationinfo[i].pretext);
1836                 FS_Print(file, "*/\n");
1837                 FS_Print(file, builtinshaderstring);
1838                 FS_Close(file);
1839                 Con_Printf("glsl/default.glsl written\n");
1840         }
1841         else
1842                 Con_Printf("failed to write to glsl/default.glsl\n");
1843
1844         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1845         if (file)
1846         {
1847                 FS_Print(file, "/* The engine may define the following macros:\n");
1848                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1849                 for (i = 0;i < SHADERMODE_COUNT;i++)
1850                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1851                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1852                         FS_Print(file, shaderpermutationinfo[i].pretext);
1853                 FS_Print(file, "*/\n");
1854                 FS_Print(file, builtinhlslshaderstring);
1855                 FS_Close(file);
1856                 Con_Printf("hlsl/default.hlsl written\n");
1857         }
1858         else
1859                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1860 }
1861
1862 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1863 {
1864         if (!second)
1865                 texturemode = GL_MODULATE;
1866         switch (vid.renderpath)
1867         {
1868         case RENDERPATH_D3D9:
1869 #ifdef SUPPORTD3D
1870                 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))));
1871                 R_Mesh_TexBind(GL20TU_FIRST , first );
1872                 R_Mesh_TexBind(GL20TU_SECOND, second);
1873 #endif
1874                 break;
1875         case RENDERPATH_D3D10:
1876                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1877                 break;
1878         case RENDERPATH_D3D11:
1879                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1880                 break;
1881         case RENDERPATH_GL20:
1882         case RENDERPATH_GLES2:
1883                 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))));
1884                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1885                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1886                 break;
1887         case RENDERPATH_GL13:
1888                 R_Mesh_TexBind(0, first );
1889                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1890                 R_Mesh_TexBind(1, second);
1891                 if (second)
1892                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1893                 break;
1894         case RENDERPATH_GL11:
1895                 R_Mesh_TexBind(0, first );
1896                 break;
1897         case RENDERPATH_SOFT:
1898                 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))));
1899                 R_Mesh_TexBind(GL20TU_FIRST , first );
1900                 R_Mesh_TexBind(GL20TU_SECOND, second);
1901                 break;
1902         }
1903 }
1904
1905 void R_SetupShader_DepthOrShadow(void)
1906 {
1907         switch (vid.renderpath)
1908         {
1909         case RENDERPATH_D3D9:
1910 #ifdef SUPPORTD3D
1911                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1912 #endif
1913                 break;
1914         case RENDERPATH_D3D10:
1915                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1916                 break;
1917         case RENDERPATH_D3D11:
1918                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1919                 break;
1920         case RENDERPATH_GL20:
1921         case RENDERPATH_GLES2:
1922                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1923                 break;
1924         case RENDERPATH_GL13:
1925                 R_Mesh_TexBind(0, 0);
1926                 R_Mesh_TexBind(1, 0);
1927                 break;
1928         case RENDERPATH_GL11:
1929                 R_Mesh_TexBind(0, 0);
1930                 break;
1931         case RENDERPATH_SOFT:
1932                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1933                 break;
1934         }
1935 }
1936
1937 void R_SetupShader_ShowDepth(void)
1938 {
1939         switch (vid.renderpath)
1940         {
1941         case RENDERPATH_D3D9:
1942 #ifdef SUPPORTHLSL
1943                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1944 #endif
1945                 break;
1946         case RENDERPATH_D3D10:
1947                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1948                 break;
1949         case RENDERPATH_D3D11:
1950                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1951                 break;
1952         case RENDERPATH_GL20:
1953         case RENDERPATH_GLES2:
1954                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1955                 break;
1956         case RENDERPATH_GL13:
1957                 break;
1958         case RENDERPATH_GL11:
1959                 break;
1960         case RENDERPATH_SOFT:
1961                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1962                 break;
1963         }
1964 }
1965
1966 extern qboolean r_shadow_usingdeferredprepass;
1967 extern cvar_t r_shadow_deferred_8bitrange;
1968 extern rtexture_t *r_shadow_attenuationgradienttexture;
1969 extern rtexture_t *r_shadow_attenuation2dtexture;
1970 extern rtexture_t *r_shadow_attenuation3dtexture;
1971 extern qboolean r_shadow_usingshadowmap2d;
1972 extern qboolean r_shadow_usingshadowmaportho;
1973 extern float r_shadow_shadowmap_texturescale[2];
1974 extern float r_shadow_shadowmap_parameters[4];
1975 extern qboolean r_shadow_shadowmapvsdct;
1976 extern qboolean r_shadow_shadowmapsampler;
1977 extern int r_shadow_shadowmappcf;
1978 extern rtexture_t *r_shadow_shadowmap2dtexture;
1979 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1980 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1981 extern matrix4x4_t r_shadow_shadowmapmatrix;
1982 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1983 extern int r_shadow_prepass_width;
1984 extern int r_shadow_prepass_height;
1985 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1986 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1987 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
1988 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
1989 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
1990
1991 #define BLENDFUNC_ALLOWS_COLORMOD     1
1992 #define BLENDFUNC_ALLOWS_FOG          2
1993 #define BLENDFUNC_ALLOWS_FOG_HACK0    4
1994 #define BLENDFUNC_ALLOWS_ANYFOG       6
1995 static int R_BlendFuncFlags(int src, int dst)
1996 {
1997         int r = 0;
1998
1999         // a blendfunc allows colormod if:
2000         // a) it can never keep the destination pixel invariant, or
2001         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2002         // this is to prevent unintended side effects from colormod
2003
2004         // a blendfunc allows fog if:
2005         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2006         // this is to prevent unintended side effects from fog
2007
2008         // these checks are the output of fogeval.pl
2009
2010         r |= BLENDFUNC_ALLOWS_COLORMOD;
2011         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2012         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2013         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2014         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2015         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2016         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2017         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2018         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2019         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2020         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2021         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2022         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2023         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2024         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2025         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2026         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2027         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2028         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2029         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2030         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2031
2032         return r;
2033 }
2034
2035 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)
2036 {
2037         // select a permutation of the lighting shader appropriate to this
2038         // combination of texture, entity, light source, and fogging, only use the
2039         // minimum features necessary to avoid wasting rendering time in the
2040         // fragment shader on features that are not being used
2041         unsigned int permutation = 0;
2042         unsigned int mode = 0;
2043         int blendfuncflags;
2044         static float dummy_colormod[3] = {1, 1, 1};
2045         float *colormod = rsurface.colormod;
2046         float m16f[16];
2047         matrix4x4_t tempmatrix;
2048         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2049         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2050                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2051         if (rsurfacepass == RSURFPASS_BACKGROUND)
2052         {
2053                 // distorted background
2054                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2055                 {
2056                         mode = SHADERMODE_WATER;
2057                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2058                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2059                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2060                         {
2061                                 // this is the right thing to do for wateralpha
2062                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2063                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2064                         }
2065                         else
2066                         {
2067                                 // this is the right thing to do for entity alpha
2068                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2069                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2070                         }
2071                 }
2072                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2073                 {
2074                         mode = SHADERMODE_REFRACTION;
2075                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2076                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2077                 }
2078                 else
2079                 {
2080                         mode = SHADERMODE_GENERIC;
2081                         permutation |= SHADERPERMUTATION_DIFFUSE;
2082                         GL_BlendFunc(GL_ONE, GL_ZERO);
2083                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2084                 }
2085         }
2086         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2087         {
2088                 if (r_glsl_offsetmapping.integer)
2089                 {
2090                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2091                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2092                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2093                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2094                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2095                         {
2096                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2097                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2098                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2099                         }
2100                 }
2101                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2102                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2103                 // normalmap (deferred prepass), may use alpha test on diffuse
2104                 mode = SHADERMODE_DEFERREDGEOMETRY;
2105                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2106                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2107                 GL_BlendFunc(GL_ONE, GL_ZERO);
2108                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2109         }
2110         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2111         {
2112                 if (r_glsl_offsetmapping.integer)
2113                 {
2114                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2115                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2116                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2117                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2118                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2119                         {
2120                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2121                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2122                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2123                         }
2124                 }
2125                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2126                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2127                 // light source
2128                 mode = SHADERMODE_LIGHTSOURCE;
2129                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2130                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2131                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2132                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2133                 if (diffusescale > 0)
2134                         permutation |= SHADERPERMUTATION_DIFFUSE;
2135                 if (specularscale > 0)
2136                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2137                 if (r_refdef.fogenabled)
2138                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2139                 if (rsurface.texture->colormapping)
2140                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2141                 if (r_shadow_usingshadowmap2d)
2142                 {
2143                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2144                         if(r_shadow_shadowmapvsdct)
2145                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2146
2147                         if (r_shadow_shadowmapsampler)
2148                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2149                         if (r_shadow_shadowmappcf > 1)
2150                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2151                         else if (r_shadow_shadowmappcf)
2152                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2153                 }
2154                 if (rsurface.texture->reflectmasktexture)
2155                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2156                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2157                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2158         }
2159         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2160         {
2161                 if (r_glsl_offsetmapping.integer)
2162                 {
2163                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2164                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2165                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2166                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2167                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2168                         {
2169                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2170                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2171                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2172                         }
2173                 }
2174                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2175                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2176                 // unshaded geometry (fullbright or ambient model lighting)
2177                 mode = SHADERMODE_FLATCOLOR;
2178                 ambientscale = diffusescale = specularscale = 0;
2179                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2180                         permutation |= SHADERPERMUTATION_GLOW;
2181                 if (r_refdef.fogenabled)
2182                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2183                 if (rsurface.texture->colormapping)
2184                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2185                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2186                 {
2187                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2188                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2189
2190                         if (r_shadow_shadowmapsampler)
2191                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2192                         if (r_shadow_shadowmappcf > 1)
2193                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2194                         else if (r_shadow_shadowmappcf)
2195                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2196                 }
2197                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2198                         permutation |= SHADERPERMUTATION_REFLECTION;
2199                 if (rsurface.texture->reflectmasktexture)
2200                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2201                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2202                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2203         }
2204         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2205         {
2206                 if (r_glsl_offsetmapping.integer)
2207                 {
2208                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2209                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2210                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2211                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2212                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2213                         {
2214                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2215                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2216                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2217                         }
2218                 }
2219                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2220                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2221                 // directional model lighting
2222                 mode = SHADERMODE_LIGHTDIRECTION;
2223                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2224                         permutation |= SHADERPERMUTATION_GLOW;
2225                 permutation |= SHADERPERMUTATION_DIFFUSE;
2226                 if (specularscale > 0)
2227                         permutation |= SHADERPERMUTATION_SPECULAR;
2228                 if (r_refdef.fogenabled)
2229                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2230                 if (rsurface.texture->colormapping)
2231                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2232                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2233                 {
2234                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2235                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2236
2237                         if (r_shadow_shadowmapsampler)
2238                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2239                         if (r_shadow_shadowmappcf > 1)
2240                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2241                         else if (r_shadow_shadowmappcf)
2242                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2243                 }
2244                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2245                         permutation |= SHADERPERMUTATION_REFLECTION;
2246                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2247                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2248                 if (rsurface.texture->reflectmasktexture)
2249                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2250                 if (r_shadow_bouncegridtexture)
2251                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2252                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2253                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2254         }
2255         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2256         {
2257                 if (r_glsl_offsetmapping.integer)
2258                 {
2259                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2260                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2261                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2262                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2263                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2264                         {
2265                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2266                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2267                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2268                         }
2269                 }
2270                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2271                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2272                 // ambient model lighting
2273                 mode = SHADERMODE_LIGHTDIRECTION;
2274                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2275                         permutation |= SHADERPERMUTATION_GLOW;
2276                 if (r_refdef.fogenabled)
2277                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2278                 if (rsurface.texture->colormapping)
2279                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2280                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2281                 {
2282                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2283                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2284
2285                         if (r_shadow_shadowmapsampler)
2286                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2287                         if (r_shadow_shadowmappcf > 1)
2288                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2289                         else if (r_shadow_shadowmappcf)
2290                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2291                 }
2292                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2293                         permutation |= SHADERPERMUTATION_REFLECTION;
2294                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2295                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2296                 if (rsurface.texture->reflectmasktexture)
2297                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2298                 if (r_shadow_bouncegridtexture)
2299                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2300                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2301                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2302         }
2303         else
2304         {
2305                 if (r_glsl_offsetmapping.integer)
2306                 {
2307                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2308                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2309                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2310                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2311                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2312                         {
2313                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2314                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2315                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2316                         }
2317                 }
2318                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2319                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2320                 // lightmapped wall
2321                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2322                         permutation |= SHADERPERMUTATION_GLOW;
2323                 if (r_refdef.fogenabled)
2324                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2325                 if (rsurface.texture->colormapping)
2326                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2327                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2328                 {
2329                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2330                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2331
2332                         if (r_shadow_shadowmapsampler)
2333                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2334                         if (r_shadow_shadowmappcf > 1)
2335                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2336                         else if (r_shadow_shadowmappcf)
2337                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2338                 }
2339                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2340                         permutation |= SHADERPERMUTATION_REFLECTION;
2341                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2342                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2343                 if (rsurface.texture->reflectmasktexture)
2344                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2345                 if (FAKELIGHT_ENABLED)
2346                 {
2347                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2348                         mode = SHADERMODE_FAKELIGHT;
2349                         permutation |= SHADERPERMUTATION_DIFFUSE;
2350                         if (specularscale > 0)
2351                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2352                 }
2353                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2354                 {
2355                         // deluxemapping (light direction texture)
2356                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2357                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2358                         else
2359                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2360                         permutation |= SHADERPERMUTATION_DIFFUSE;
2361                         if (specularscale > 0)
2362                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2363                 }
2364                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2365                 {
2366                         // fake deluxemapping (uniform light direction in tangentspace)
2367                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2368                         permutation |= SHADERPERMUTATION_DIFFUSE;
2369                         if (specularscale > 0)
2370                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2371                 }
2372                 else if (rsurface.uselightmaptexture)
2373                 {
2374                         // ordinary lightmapping (q1bsp, q3bsp)
2375                         mode = SHADERMODE_LIGHTMAP;
2376                 }
2377                 else
2378                 {
2379                         // ordinary vertex coloring (q3bsp)
2380                         mode = SHADERMODE_VERTEXCOLOR;
2381                 }
2382                 if (r_shadow_bouncegridtexture)
2383                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2384                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2385                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2386         }
2387         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2388                 colormod = dummy_colormod;
2389         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2390                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2391         switch(vid.renderpath)
2392         {
2393         case RENDERPATH_D3D9:
2394 #ifdef SUPPORTD3D
2395                 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);
2396                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2397                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2398                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2399                 if (mode == SHADERMODE_LIGHTSOURCE)
2400                 {
2401                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2402                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2403                 }
2404                 else
2405                 {
2406                         if (mode == SHADERMODE_LIGHTDIRECTION)
2407                         {
2408                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2409                         }
2410                 }
2411                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2412                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2413                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2414                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2415                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2416
2417                 if (mode == SHADERMODE_LIGHTSOURCE)
2418                 {
2419                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2420                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2421                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2422                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2423                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2424
2425                         // additive passes are only darkened by fog, not tinted
2426                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2427                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2428                 }
2429                 else
2430                 {
2431                         if (mode == SHADERMODE_FLATCOLOR)
2432                         {
2433                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2434                         }
2435                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2436                         {
2437                                 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]);
2438                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2439                                 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);
2440                                 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);
2441                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2442                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2443                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2444                         }
2445                         else
2446                         {
2447                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2448                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2449                                 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);
2450                                 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);
2451                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2452                         }
2453                         // additive passes are only darkened by fog, not tinted
2454                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2455                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2456                         else
2457                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2458                         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);
2459                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2460                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2461                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2462                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2463                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2464                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2465                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2466                         if (mode == SHADERMODE_WATER)
2467                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2468                 }
2469                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2470                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2471                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2472                 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));
2473                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2474                 if (rsurface.texture->pantstexture)
2475                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2476                 else
2477                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2478                 if (rsurface.texture->shirttexture)
2479                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2480                 else
2481                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2482                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2483                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2484                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2485                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2486                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2487                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2488                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2489
2490                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2491                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2492                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2493                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2494                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2495                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2496                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2497                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2498                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2499                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2500                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2501                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2502                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2503                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2504                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2505                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2506                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2507                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2508                 {
2509                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2510                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2511                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2512                 }
2513                 else
2514                 {
2515                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2516                 }
2517 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2518 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2519                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2520                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2521                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2522                 {
2523                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2524                         if (rsurface.rtlight)
2525                         {
2526                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2527                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2528                         }
2529                 }
2530 #endif
2531                 break;
2532         case RENDERPATH_D3D10:
2533                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2534                 break;
2535         case RENDERPATH_D3D11:
2536                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2537                 break;
2538         case RENDERPATH_GL20:
2539         case RENDERPATH_GLES2:
2540                 if (!vid.useinterleavedarrays)
2541                 {
2542                         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);
2543                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2544                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2545                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2546                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2547                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2548                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2549                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2550                 }
2551                 else
2552                 {
2553                         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);
2554                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2555                 }
2556                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2557                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2558                 if (mode == SHADERMODE_LIGHTSOURCE)
2559                 {
2560                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2561                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2562                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2563                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2564                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2565                         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);
2566         
2567                         // additive passes are only darkened by fog, not tinted
2568                         if (r_glsl_permutation->loc_FogColor >= 0)
2569                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2570                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2571                 }
2572                 else
2573                 {
2574                         if (mode == SHADERMODE_FLATCOLOR)
2575                         {
2576                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2577                         }
2578                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2579                         {
2580                                 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]);
2581                                 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]);
2582                                 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);
2583                                 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);
2584                                 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);
2585                                 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]);
2586                                 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]);
2587                         }
2588                         else
2589                         {
2590                                 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]);
2591                                 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]);
2592                                 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);
2593                                 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);
2594                                 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);
2595                         }
2596                         // additive passes are only darkened by fog, not tinted
2597                         if (r_glsl_permutation->loc_FogColor >= 0)
2598                         {
2599                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2600                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2601                                 else
2602                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2603                         }
2604                         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);
2605                         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]);
2606                         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]);
2607                         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]);
2608                         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]);
2609                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2610                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2611                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2612                         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]);
2613                 }
2614                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2615                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2616                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2617                 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]);
2618                 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]);
2619
2620                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2621                 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));
2622                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2623                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2624                 {
2625                         if (rsurface.texture->pantstexture)
2626                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2627                         else
2628                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2629                 }
2630                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2631                 {
2632                         if (rsurface.texture->shirttexture)
2633                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2634                         else
2635                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2636                 }
2637                 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]);
2638                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2639                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2640                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2641                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2642                 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]);
2643                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2644                 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);}
2645                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2646
2647                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2648                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2649                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2650                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2651                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2652                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2653                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2654                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2655                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2656                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2657                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2658                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2659                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2660                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2661                 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);
2662                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2663                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2664                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2665                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2666                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2667                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2668                 {
2669                         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);
2670                         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);
2671                         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);
2672                 }
2673                 else
2674                 {
2675                         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);
2676                 }
2677                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2678                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2679                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2680                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2681                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2682                 {
2683                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2684                         if (rsurface.rtlight)
2685                         {
2686                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2687                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2688                         }
2689                 }
2690                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2691                 CHECKGLERROR
2692                 break;
2693         case RENDERPATH_GL13:
2694         case RENDERPATH_GL11:
2695                 break;
2696         case RENDERPATH_SOFT:
2697                 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);
2698                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2699                 R_SetupShader_SetPermutationSoft(mode, permutation);
2700                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2701                 if (mode == SHADERMODE_LIGHTSOURCE)
2702                 {
2703                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2704                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2705                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2706                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2707                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2708                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2709         
2710                         // additive passes are only darkened by fog, not tinted
2711                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2712                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2713                 }
2714                 else
2715                 {
2716                         if (mode == SHADERMODE_FLATCOLOR)
2717                         {
2718                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2719                         }
2720                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2721                         {
2722                                 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]);
2723                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2724                                 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);
2725                                 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);
2726                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2727                                 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]);
2728                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2729                         }
2730                         else
2731                         {
2732                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2733                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2734                                 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);
2735                                 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);
2736                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2737                         }
2738                         // additive passes are only darkened by fog, not tinted
2739                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2740                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2741                         else
2742                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2743                         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);
2744                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2745                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2746                         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]);
2747                         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]);
2748                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2749                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2750                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2751                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2752                 }
2753                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2754                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2755                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2756                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2757                 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]);
2758
2759                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2760                 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));
2761                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2762                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2763                 {
2764                         if (rsurface.texture->pantstexture)
2765                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2766                         else
2767                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2768                 }
2769                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2770                 {
2771                         if (rsurface.texture->shirttexture)
2772                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2773                         else
2774                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2775                 }
2776                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2777                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2778                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2779                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2780                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2781                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2782                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2783
2784                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2785                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2786                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2787                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2788                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2789                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2790                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2791                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2792                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2793                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2794                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2795                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2796                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2797                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2798                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2799                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2800                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2801                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2802                 {
2803                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2804                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2805                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2806                 }
2807                 else
2808                 {
2809                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2810                 }
2811 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2812 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2813                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2814                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2815                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2816                 {
2817                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2818                         if (rsurface.rtlight)
2819                         {
2820                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2821                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2822                         }
2823                 }
2824                 break;
2825         }
2826 }
2827
2828 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2829 {
2830         // select a permutation of the lighting shader appropriate to this
2831         // combination of texture, entity, light source, and fogging, only use the
2832         // minimum features necessary to avoid wasting rendering time in the
2833         // fragment shader on features that are not being used
2834         unsigned int permutation = 0;
2835         unsigned int mode = 0;
2836         const float *lightcolorbase = rtlight->currentcolor;
2837         float ambientscale = rtlight->ambientscale;
2838         float diffusescale = rtlight->diffusescale;
2839         float specularscale = rtlight->specularscale;
2840         // this is the location of the light in view space
2841         vec3_t viewlightorigin;
2842         // this transforms from view space (camera) to light space (cubemap)
2843         matrix4x4_t viewtolight;
2844         matrix4x4_t lighttoview;
2845         float viewtolight16f[16];
2846         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2847         // light source
2848         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2849         if (rtlight->currentcubemap != r_texture_whitecube)
2850                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2851         if (diffusescale > 0)
2852                 permutation |= SHADERPERMUTATION_DIFFUSE;
2853         if (specularscale > 0)
2854                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2855         if (r_shadow_usingshadowmap2d)
2856         {
2857                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2858                 if (r_shadow_shadowmapvsdct)
2859                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2860
2861                 if (r_shadow_shadowmapsampler)
2862                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2863                 if (r_shadow_shadowmappcf > 1)
2864                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2865                 else if (r_shadow_shadowmappcf)
2866                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2867         }
2868         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2869         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2870         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2871         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2872         switch(vid.renderpath)
2873         {
2874         case RENDERPATH_D3D9:
2875 #ifdef SUPPORTD3D
2876                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2877                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2878                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2879                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2880                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2881                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2882                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2883                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2884                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2885                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2886                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2887
2888                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2889                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2890                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2891                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2892                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2893                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2894 #endif
2895                 break;
2896         case RENDERPATH_D3D10:
2897                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2898                 break;
2899         case RENDERPATH_D3D11:
2900                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2901                 break;
2902         case RENDERPATH_GL20:
2903         case RENDERPATH_GLES2:
2904                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2905                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2906                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2907                 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);
2908                 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);
2909                 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);
2910                 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]);
2911                 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]);
2912                 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));
2913                 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]);
2914                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2915
2916                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2917                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2918                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2919                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2920                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2921                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2922                 break;
2923         case RENDERPATH_GL13:
2924         case RENDERPATH_GL11:
2925                 break;
2926         case RENDERPATH_SOFT:
2927                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2928                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2929                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2930                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2931                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2932                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2933                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2934                 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]);
2935                 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));
2936                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2937                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2938
2939                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2940                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2941                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2942                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2943                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2944                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2945                 break;
2946         }
2947 }
2948
2949 #define SKINFRAME_HASH 1024
2950
2951 typedef struct
2952 {
2953         int loadsequence; // incremented each level change
2954         memexpandablearray_t array;
2955         skinframe_t *hash[SKINFRAME_HASH];
2956 }
2957 r_skinframe_t;
2958 r_skinframe_t r_skinframe;
2959
2960 void R_SkinFrame_PrepareForPurge(void)
2961 {
2962         r_skinframe.loadsequence++;
2963         // wrap it without hitting zero
2964         if (r_skinframe.loadsequence >= 200)
2965                 r_skinframe.loadsequence = 1;
2966 }
2967
2968 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2969 {
2970         if (!skinframe)
2971                 return;
2972         // mark the skinframe as used for the purging code
2973         skinframe->loadsequence = r_skinframe.loadsequence;
2974 }
2975
2976 void R_SkinFrame_Purge(void)
2977 {
2978         int i;
2979         skinframe_t *s;
2980         for (i = 0;i < SKINFRAME_HASH;i++)
2981         {
2982                 for (s = r_skinframe.hash[i];s;s = s->next)
2983                 {
2984                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2985                         {
2986                                 if (s->merged == s->base)
2987                                         s->merged = NULL;
2988                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2989                                 R_PurgeTexture(s->stain );s->stain  = NULL;
2990                                 R_PurgeTexture(s->merged);s->merged = NULL;
2991                                 R_PurgeTexture(s->base  );s->base   = NULL;
2992                                 R_PurgeTexture(s->pants );s->pants  = NULL;
2993                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
2994                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
2995                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
2996                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
2997                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
2998                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
2999                                 s->loadsequence = 0;
3000                         }
3001                 }
3002         }
3003 }
3004
3005 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3006         skinframe_t *item;
3007         char basename[MAX_QPATH];
3008
3009         Image_StripImageExtension(name, basename, sizeof(basename));
3010
3011         if( last == NULL ) {
3012                 int hashindex;
3013                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3014                 item = r_skinframe.hash[hashindex];
3015         } else {
3016                 item = last->next;
3017         }
3018
3019         // linearly search through the hash bucket
3020         for( ; item ; item = item->next ) {
3021                 if( !strcmp( item->basename, basename ) ) {
3022                         return item;
3023                 }
3024         }
3025         return NULL;
3026 }
3027
3028 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3029 {
3030         skinframe_t *item;
3031         int hashindex;
3032         char basename[MAX_QPATH];
3033
3034         Image_StripImageExtension(name, basename, sizeof(basename));
3035
3036         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3037         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3038                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3039                         break;
3040
3041         if (!item) {
3042                 rtexture_t *dyntexture;
3043                 // check whether its a dynamic texture
3044                 dyntexture = CL_GetDynTexture( basename );
3045                 if (!add && !dyntexture)
3046                         return NULL;
3047                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3048                 memset(item, 0, sizeof(*item));
3049                 strlcpy(item->basename, basename, sizeof(item->basename));
3050                 item->base = dyntexture; // either NULL or dyntexture handle
3051                 item->textureflags = textureflags;
3052                 item->comparewidth = comparewidth;
3053                 item->compareheight = compareheight;
3054                 item->comparecrc = comparecrc;
3055                 item->next = r_skinframe.hash[hashindex];
3056                 r_skinframe.hash[hashindex] = item;
3057         }
3058         else if( item->base == NULL )
3059         {
3060                 rtexture_t *dyntexture;
3061                 // check whether its a dynamic texture
3062                 // 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]
3063                 dyntexture = CL_GetDynTexture( basename );
3064                 item->base = dyntexture; // either NULL or dyntexture handle
3065         }
3066
3067         R_SkinFrame_MarkUsed(item);
3068         return item;
3069 }
3070
3071 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3072         { \
3073                 unsigned long long avgcolor[5], wsum; \
3074                 int pix, comp, w; \
3075                 avgcolor[0] = 0; \
3076                 avgcolor[1] = 0; \
3077                 avgcolor[2] = 0; \
3078                 avgcolor[3] = 0; \
3079                 avgcolor[4] = 0; \
3080                 wsum = 0; \
3081                 for(pix = 0; pix < cnt; ++pix) \
3082                 { \
3083                         w = 0; \
3084                         for(comp = 0; comp < 3; ++comp) \
3085                                 w += getpixel; \
3086                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3087                         { \
3088                                 ++wsum; \
3089                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3090                                 w = getpixel; \
3091                                 for(comp = 0; comp < 3; ++comp) \
3092                                         avgcolor[comp] += getpixel * w; \
3093                                 avgcolor[3] += w; \
3094                         } \
3095                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3096                         avgcolor[4] += getpixel; \
3097                 } \
3098                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3099                         avgcolor[3] = 1; \
3100                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3101                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3102                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3103                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3104         }
3105
3106 extern cvar_t gl_picmip;
3107 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3108 {
3109         int j;
3110         unsigned char *pixels;
3111         unsigned char *bumppixels;
3112         unsigned char *basepixels = NULL;
3113         int basepixels_width = 0;
3114         int basepixels_height = 0;
3115         skinframe_t *skinframe;
3116         rtexture_t *ddsbase = NULL;
3117         qboolean ddshasalpha = false;
3118         float ddsavgcolor[4];
3119         char basename[MAX_QPATH];
3120         int miplevel = R_PicmipForFlags(textureflags);
3121         int savemiplevel = miplevel;
3122         int mymiplevel;
3123
3124         if (cls.state == ca_dedicated)
3125                 return NULL;
3126
3127         // return an existing skinframe if already loaded
3128         // if loading of the first image fails, don't make a new skinframe as it
3129         // would cause all future lookups of this to be missing
3130         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3131         if (skinframe && skinframe->base)
3132                 return skinframe;
3133
3134         Image_StripImageExtension(name, basename, sizeof(basename));
3135
3136         // check for DDS texture file first
3137         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3138         {
3139                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3140                 if (basepixels == NULL)
3141                         return NULL;
3142         }
3143
3144         // FIXME handle miplevel
3145
3146         if (developer_loading.integer)
3147                 Con_Printf("loading skin \"%s\"\n", name);
3148
3149         // we've got some pixels to store, so really allocate this new texture now
3150         if (!skinframe)
3151                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3152         skinframe->stain = NULL;
3153         skinframe->merged = NULL;
3154         skinframe->base = NULL;
3155         skinframe->pants = NULL;
3156         skinframe->shirt = NULL;
3157         skinframe->nmap = NULL;
3158         skinframe->gloss = NULL;
3159         skinframe->glow = NULL;
3160         skinframe->fog = NULL;
3161         skinframe->reflect = NULL;
3162         skinframe->hasalpha = false;
3163
3164         if (ddsbase)
3165         {
3166                 skinframe->base = ddsbase;
3167                 skinframe->hasalpha = ddshasalpha;
3168                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3169                 if (r_loadfog && skinframe->hasalpha)
3170                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3171                 //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]);
3172         }
3173         else
3174         {
3175                 basepixels_width = image_width;
3176                 basepixels_height = image_height;
3177                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3178                 if (textureflags & TEXF_ALPHA)
3179                 {
3180                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3181                         {
3182                                 if (basepixels[j] < 255)
3183                                 {
3184                                         skinframe->hasalpha = true;
3185                                         break;
3186                                 }
3187                         }
3188                         if (r_loadfog && skinframe->hasalpha)
3189                         {
3190                                 // has transparent pixels
3191                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3192                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3193                                 {
3194                                         pixels[j+0] = 255;
3195                                         pixels[j+1] = 255;
3196                                         pixels[j+2] = 255;
3197                                         pixels[j+3] = basepixels[j+3];
3198                                 }
3199                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3200                                 Mem_Free(pixels);
3201                         }
3202                 }
3203                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3204                 //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]);
3205                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3206                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3207                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3208                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3209         }
3210
3211         if (r_loaddds)
3212         {
3213                 mymiplevel = savemiplevel;
3214                 if (r_loadnormalmap)
3215                         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);
3216                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3217                 if (r_loadgloss)
3218                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3219                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3220                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3221                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3222         }
3223
3224         // _norm is the name used by tenebrae and has been adopted as standard
3225         if (r_loadnormalmap && skinframe->nmap == NULL)
3226         {
3227                 mymiplevel = savemiplevel;
3228                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3229                 {
3230                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3231                         Mem_Free(pixels);
3232                         pixels = NULL;
3233                 }
3234                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3235                 {
3236                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3237                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3238                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3239                         Mem_Free(pixels);
3240                         Mem_Free(bumppixels);
3241                 }
3242                 else if (r_shadow_bumpscale_basetexture.value > 0)
3243                 {
3244                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3245                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3246                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3247                         Mem_Free(pixels);
3248                 }
3249                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3250                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3251         }
3252
3253         // _luma is supported only for tenebrae compatibility
3254         // _glow is the preferred name
3255         mymiplevel = savemiplevel;
3256         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
3257         {
3258                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3259                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3260                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3261                 Mem_Free(pixels);pixels = NULL;
3262         }
3263
3264         mymiplevel = savemiplevel;
3265         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3266         {
3267                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3268                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3269                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3270                 Mem_Free(pixels);
3271                 pixels = NULL;
3272         }
3273
3274         mymiplevel = savemiplevel;
3275         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3276         {
3277                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3278                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3279                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3280                 Mem_Free(pixels);
3281                 pixels = NULL;
3282         }
3283
3284         mymiplevel = savemiplevel;
3285         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3286         {
3287                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3288                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3289                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3290                 Mem_Free(pixels);
3291                 pixels = NULL;
3292         }
3293
3294         mymiplevel = savemiplevel;
3295         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3296         {
3297                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3298                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3299                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3300                 Mem_Free(pixels);
3301                 pixels = NULL;
3302         }
3303
3304         if (basepixels)
3305                 Mem_Free(basepixels);
3306
3307         return skinframe;
3308 }
3309
3310 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3311 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3312 {
3313         int i;
3314         unsigned char *temp1, *temp2;
3315         skinframe_t *skinframe;
3316
3317         if (cls.state == ca_dedicated)
3318                 return NULL;
3319
3320         // if already loaded just return it, otherwise make a new skinframe
3321         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3322         if (skinframe && skinframe->base)
3323                 return skinframe;
3324
3325         skinframe->stain = NULL;
3326         skinframe->merged = NULL;
3327         skinframe->base = NULL;
3328         skinframe->pants = NULL;
3329         skinframe->shirt = NULL;
3330         skinframe->nmap = NULL;
3331         skinframe->gloss = NULL;
3332         skinframe->glow = NULL;
3333         skinframe->fog = NULL;
3334         skinframe->reflect = NULL;
3335         skinframe->hasalpha = false;
3336
3337         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3338         if (!skindata)
3339                 return NULL;
3340
3341         if (developer_loading.integer)
3342                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3343
3344         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3345         {
3346                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3347                 temp2 = temp1 + width * height * 4;
3348                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3349                 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);
3350                 Mem_Free(temp1);
3351         }
3352         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3353         if (textureflags & TEXF_ALPHA)
3354         {
3355                 for (i = 3;i < width * height * 4;i += 4)
3356                 {
3357                         if (skindata[i] < 255)
3358                         {
3359                                 skinframe->hasalpha = true;
3360                                 break;
3361                         }
3362                 }
3363                 if (r_loadfog && skinframe->hasalpha)
3364                 {
3365                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3366                         memcpy(fogpixels, skindata, width * height * 4);
3367                         for (i = 0;i < width * height * 4;i += 4)
3368                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3369                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3370                         Mem_Free(fogpixels);
3371                 }
3372         }
3373
3374         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3375         //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]);
3376
3377         return skinframe;
3378 }
3379
3380 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3381 {
3382         int i;
3383         int featuresmask;
3384         skinframe_t *skinframe;
3385
3386         if (cls.state == ca_dedicated)
3387                 return NULL;
3388
3389         // if already loaded just return it, otherwise make a new skinframe
3390         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3391         if (skinframe && skinframe->base)
3392                 return skinframe;
3393
3394         skinframe->stain = NULL;
3395         skinframe->merged = NULL;
3396         skinframe->base = NULL;
3397         skinframe->pants = NULL;
3398         skinframe->shirt = NULL;
3399         skinframe->nmap = NULL;
3400         skinframe->gloss = NULL;
3401         skinframe->glow = NULL;
3402         skinframe->fog = NULL;
3403         skinframe->reflect = NULL;
3404         skinframe->hasalpha = false;
3405
3406         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3407         if (!skindata)
3408                 return NULL;
3409
3410         if (developer_loading.integer)
3411                 Con_Printf("loading quake skin \"%s\"\n", name);
3412
3413         // 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)
3414         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3415         memcpy(skinframe->qpixels, skindata, width*height);
3416         skinframe->qwidth = width;
3417         skinframe->qheight = height;
3418
3419         featuresmask = 0;
3420         for (i = 0;i < width * height;i++)
3421                 featuresmask |= palette_featureflags[skindata[i]];
3422
3423         skinframe->hasalpha = false;
3424         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3425         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3426         skinframe->qgeneratemerged = true;
3427         skinframe->qgeneratebase = skinframe->qhascolormapping;
3428         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3429
3430         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3431         //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]);
3432
3433         return skinframe;
3434 }
3435
3436 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3437 {
3438         int width;
3439         int height;
3440         unsigned char *skindata;
3441
3442         if (!skinframe->qpixels)
3443                 return;
3444
3445         if (!skinframe->qhascolormapping)
3446                 colormapped = false;
3447
3448         if (colormapped)
3449         {
3450                 if (!skinframe->qgeneratebase)
3451                         return;
3452         }
3453         else
3454         {
3455                 if (!skinframe->qgeneratemerged)
3456                         return;
3457         }
3458
3459         width = skinframe->qwidth;
3460         height = skinframe->qheight;
3461         skindata = skinframe->qpixels;
3462
3463         if (skinframe->qgeneratenmap)
3464         {
3465                 unsigned char *temp1, *temp2;
3466                 skinframe->qgeneratenmap = false;
3467                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3468                 temp2 = temp1 + width * height * 4;
3469                 // use either a custom palette or the quake palette
3470                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3471                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3472                 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);
3473                 Mem_Free(temp1);
3474         }
3475
3476         if (skinframe->qgenerateglow)
3477         {
3478                 skinframe->qgenerateglow = false;
3479                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3480         }
3481
3482         if (colormapped)
3483         {
3484                 skinframe->qgeneratebase = false;
3485                 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);
3486                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3487                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3488         }
3489         else
3490         {
3491                 skinframe->qgeneratemerged = false;
3492                 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);
3493         }
3494
3495         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3496         {
3497                 Mem_Free(skinframe->qpixels);
3498                 skinframe->qpixels = NULL;
3499         }
3500 }
3501
3502 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)
3503 {
3504         int i;
3505         skinframe_t *skinframe;
3506
3507         if (cls.state == ca_dedicated)
3508                 return NULL;
3509
3510         // if already loaded just return it, otherwise make a new skinframe
3511         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3512         if (skinframe && skinframe->base)
3513                 return skinframe;
3514
3515         skinframe->stain = NULL;
3516         skinframe->merged = NULL;
3517         skinframe->base = NULL;
3518         skinframe->pants = NULL;
3519         skinframe->shirt = NULL;
3520         skinframe->nmap = NULL;
3521         skinframe->gloss = NULL;
3522         skinframe->glow = NULL;
3523         skinframe->fog = NULL;
3524         skinframe->reflect = NULL;
3525         skinframe->hasalpha = false;
3526
3527         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3528         if (!skindata)
3529                 return NULL;
3530
3531         if (developer_loading.integer)
3532                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3533
3534         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3535         if (textureflags & TEXF_ALPHA)
3536         {
3537                 for (i = 0;i < width * height;i++)
3538                 {
3539                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3540                         {
3541                                 skinframe->hasalpha = true;
3542                                 break;
3543                         }
3544                 }
3545                 if (r_loadfog && skinframe->hasalpha)
3546                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3547         }
3548
3549         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3550         //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]);
3551
3552         return skinframe;
3553 }
3554
3555 skinframe_t *R_SkinFrame_LoadMissing(void)
3556 {
3557         skinframe_t *skinframe;
3558
3559         if (cls.state == ca_dedicated)
3560                 return NULL;
3561
3562         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3563         skinframe->stain = NULL;
3564         skinframe->merged = NULL;
3565         skinframe->base = NULL;
3566         skinframe->pants = NULL;
3567         skinframe->shirt = NULL;
3568         skinframe->nmap = NULL;
3569         skinframe->gloss = NULL;
3570         skinframe->glow = NULL;
3571         skinframe->fog = NULL;
3572         skinframe->reflect = NULL;
3573         skinframe->hasalpha = false;
3574
3575         skinframe->avgcolor[0] = rand() / RAND_MAX;
3576         skinframe->avgcolor[1] = rand() / RAND_MAX;
3577         skinframe->avgcolor[2] = rand() / RAND_MAX;
3578         skinframe->avgcolor[3] = 1;
3579
3580         return skinframe;
3581 }
3582
3583 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3584 typedef struct suffixinfo_s
3585 {
3586         const char *suffix;
3587         qboolean flipx, flipy, flipdiagonal;
3588 }
3589 suffixinfo_t;
3590 static suffixinfo_t suffix[3][6] =
3591 {
3592         {
3593                 {"px",   false, false, false},
3594                 {"nx",   false, false, false},
3595                 {"py",   false, false, false},
3596                 {"ny",   false, false, false},
3597                 {"pz",   false, false, false},
3598                 {"nz",   false, false, false}
3599         },
3600         {
3601                 {"posx", false, false, false},
3602                 {"negx", false, false, false},
3603                 {"posy", false, false, false},
3604                 {"negy", false, false, false},
3605                 {"posz", false, false, false},
3606                 {"negz", false, false, false}
3607         },
3608         {
3609                 {"rt",    true, false,  true},
3610                 {"lf",   false,  true,  true},
3611                 {"ft",    true,  true, false},
3612                 {"bk",   false, false, false},
3613                 {"up",    true, false,  true},
3614                 {"dn",    true, false,  true}
3615         }
3616 };
3617
3618 static int componentorder[4] = {0, 1, 2, 3};
3619
3620 rtexture_t *R_LoadCubemap(const char *basename)
3621 {
3622         int i, j, cubemapsize;
3623         unsigned char *cubemappixels, *image_buffer;
3624         rtexture_t *cubemaptexture;
3625         char name[256];
3626         // must start 0 so the first loadimagepixels has no requested width/height
3627         cubemapsize = 0;
3628         cubemappixels = NULL;
3629         cubemaptexture = NULL;
3630         // keep trying different suffix groups (posx, px, rt) until one loads
3631         for (j = 0;j < 3 && !cubemappixels;j++)
3632         {
3633                 // load the 6 images in the suffix group
3634                 for (i = 0;i < 6;i++)
3635                 {
3636                         // generate an image name based on the base and and suffix
3637                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3638                         // load it
3639                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3640                         {
3641                                 // an image loaded, make sure width and height are equal
3642                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3643                                 {
3644                                         // if this is the first image to load successfully, allocate the cubemap memory
3645                                         if (!cubemappixels && image_width >= 1)
3646                                         {
3647                                                 cubemapsize = image_width;
3648                                                 // note this clears to black, so unavailable sides are black
3649                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3650                                         }
3651                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3652                                         if (cubemappixels)
3653                                                 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);
3654                                 }
3655                                 else
3656                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3657                                 // free the image
3658                                 Mem_Free(image_buffer);
3659                         }
3660                 }
3661         }
3662         // if a cubemap loaded, upload it
3663         if (cubemappixels)
3664         {
3665                 if (developer_loading.integer)
3666                         Con_Printf("loading cubemap \"%s\"\n", basename);
3667
3668                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3669                 Mem_Free(cubemappixels);
3670         }
3671         else
3672         {
3673                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3674                 if (developer_loading.integer)
3675                 {
3676                         Con_Printf("(tried tried images ");
3677                         for (j = 0;j < 3;j++)
3678                                 for (i = 0;i < 6;i++)
3679                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3680                         Con_Print(" and was unable to find any of them).\n");
3681                 }
3682         }
3683         return cubemaptexture;
3684 }
3685
3686 rtexture_t *R_GetCubemap(const char *basename)
3687 {
3688         int i;
3689         for (i = 0;i < r_texture_numcubemaps;i++)
3690                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3691                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3692         if (i >= MAX_CUBEMAPS)
3693                 return r_texture_whitecube;
3694         r_texture_numcubemaps++;
3695         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3696         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3697         return r_texture_cubemaps[i].texture;
3698 }
3699
3700 void R_FreeCubemaps(void)
3701 {
3702         int i;
3703         for (i = 0;i < r_texture_numcubemaps;i++)
3704         {
3705                 if (developer_loading.integer)
3706                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3707                 if (r_texture_cubemaps[i].texture)
3708                         R_FreeTexture(r_texture_cubemaps[i].texture);
3709         }
3710         r_texture_numcubemaps = 0;
3711 }
3712
3713 void R_Main_FreeViewCache(void)
3714 {
3715         if (r_refdef.viewcache.entityvisible)
3716                 Mem_Free(r_refdef.viewcache.entityvisible);
3717         if (r_refdef.viewcache.world_pvsbits)
3718                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3719         if (r_refdef.viewcache.world_leafvisible)
3720                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3721         if (r_refdef.viewcache.world_surfacevisible)
3722                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3723         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3724 }
3725
3726 void R_Main_ResizeViewCache(void)
3727 {
3728         int numentities = r_refdef.scene.numentities;
3729         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3730         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3731         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3732         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3733         if (r_refdef.viewcache.maxentities < numentities)
3734         {
3735                 r_refdef.viewcache.maxentities = numentities;
3736                 if (r_refdef.viewcache.entityvisible)
3737                         Mem_Free(r_refdef.viewcache.entityvisible);
3738                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3739         }
3740         if (r_refdef.viewcache.world_numclusters != numclusters)
3741         {
3742                 r_refdef.viewcache.world_numclusters = numclusters;
3743                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3744                 if (r_refdef.viewcache.world_pvsbits)
3745                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3746                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3747         }
3748         if (r_refdef.viewcache.world_numleafs != numleafs)
3749         {
3750                 r_refdef.viewcache.world_numleafs = numleafs;
3751                 if (r_refdef.viewcache.world_leafvisible)
3752                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3753                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3754         }
3755         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3756         {
3757                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3758                 if (r_refdef.viewcache.world_surfacevisible)
3759                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3760                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3761         }
3762 }
3763
3764 extern rtexture_t *loadingscreentexture;
3765 void gl_main_start(void)
3766 {
3767         loadingscreentexture = NULL;
3768         r_texture_blanknormalmap = NULL;
3769         r_texture_white = NULL;
3770         r_texture_grey128 = NULL;
3771         r_texture_black = NULL;
3772         r_texture_whitecube = NULL;
3773         r_texture_normalizationcube = NULL;
3774         r_texture_fogattenuation = NULL;
3775         r_texture_fogheighttexture = NULL;
3776         r_texture_gammaramps = NULL;
3777         r_texture_numcubemaps = 0;
3778
3779         r_loaddds = r_texture_dds_load.integer != 0;
3780         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3781
3782         switch(vid.renderpath)
3783         {
3784         case RENDERPATH_GL20:
3785         case RENDERPATH_D3D9:
3786         case RENDERPATH_D3D10:
3787         case RENDERPATH_D3D11:
3788         case RENDERPATH_SOFT:
3789                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3790                 Cvar_SetValueQuick(&gl_combine, 1);
3791                 Cvar_SetValueQuick(&r_glsl, 1);
3792                 r_loadnormalmap = true;
3793                 r_loadgloss = true;
3794                 r_loadfog = false;
3795                 break;
3796         case RENDERPATH_GL13:
3797                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3798                 Cvar_SetValueQuick(&gl_combine, 1);
3799                 Cvar_SetValueQuick(&r_glsl, 0);
3800                 r_loadnormalmap = false;
3801                 r_loadgloss = false;
3802                 r_loadfog = true;
3803                 break;
3804         case RENDERPATH_GL11:
3805                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3806                 Cvar_SetValueQuick(&gl_combine, 0);
3807                 Cvar_SetValueQuick(&r_glsl, 0);
3808                 r_loadnormalmap = false;
3809                 r_loadgloss = false;
3810                 r_loadfog = true;
3811                 break;
3812         case RENDERPATH_GLES2:
3813                 Cvar_SetValueQuick(&r_textureunits, 1);
3814                 Cvar_SetValueQuick(&gl_combine, 1);
3815                 Cvar_SetValueQuick(&r_glsl, 1);
3816                 r_loadnormalmap = true;
3817                 r_loadgloss = false;
3818                 r_loadfog = false;
3819                 break;
3820         }
3821
3822         R_AnimCache_Free();
3823         R_FrameData_Reset();
3824
3825         r_numqueries = 0;
3826         r_maxqueries = 0;
3827         memset(r_queries, 0, sizeof(r_queries));
3828
3829         r_qwskincache = NULL;
3830         r_qwskincache_size = 0;
3831
3832         // set up r_skinframe loading system for textures
3833         memset(&r_skinframe, 0, sizeof(r_skinframe));
3834         r_skinframe.loadsequence = 1;
3835         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3836
3837         r_main_texturepool = R_AllocTexturePool();
3838         R_BuildBlankTextures();
3839         R_BuildNoTexture();
3840         if (vid.support.arb_texture_cube_map)
3841         {
3842                 R_BuildWhiteCube();
3843                 R_BuildNormalizationCube();
3844         }
3845         r_texture_fogattenuation = NULL;
3846         r_texture_fogheighttexture = NULL;
3847         r_texture_gammaramps = NULL;
3848         //r_texture_fogintensity = NULL;
3849         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3850         memset(&r_waterstate, 0, sizeof(r_waterstate));
3851         r_glsl_permutation = NULL;
3852         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3853         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3854         glslshaderstring = NULL;
3855 #ifdef SUPPORTD3D
3856         r_hlsl_permutation = NULL;
3857         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3858         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3859 #endif
3860         hlslshaderstring = NULL;
3861         memset(&r_svbsp, 0, sizeof (r_svbsp));
3862
3863         r_refdef.fogmasktable_density = 0;
3864 }
3865
3866 void gl_main_shutdown(void)
3867 {
3868         R_AnimCache_Free();
3869         R_FrameData_Reset();
3870
3871         R_Main_FreeViewCache();
3872
3873         switch(vid.renderpath)
3874         {
3875         case RENDERPATH_GL11:
3876         case RENDERPATH_GL13:
3877         case RENDERPATH_GL20:
3878         case RENDERPATH_GLES2:
3879                 if (r_maxqueries)
3880                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3881                 break;
3882         case RENDERPATH_D3D9:
3883                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3884                 break;
3885         case RENDERPATH_D3D10:
3886                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3887                 break;
3888         case RENDERPATH_D3D11:
3889                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3890                 break;
3891         case RENDERPATH_SOFT:
3892                 break;
3893         }
3894
3895         r_numqueries = 0;
3896         r_maxqueries = 0;
3897         memset(r_queries, 0, sizeof(r_queries));
3898
3899         r_qwskincache = NULL;
3900         r_qwskincache_size = 0;
3901
3902         // clear out the r_skinframe state
3903         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3904         memset(&r_skinframe, 0, sizeof(r_skinframe));
3905
3906         if (r_svbsp.nodes)
3907                 Mem_Free(r_svbsp.nodes);
3908         memset(&r_svbsp, 0, sizeof (r_svbsp));
3909         R_FreeTexturePool(&r_main_texturepool);
3910         loadingscreentexture = NULL;
3911         r_texture_blanknormalmap = NULL;
3912         r_texture_white = NULL;
3913         r_texture_grey128 = NULL;
3914         r_texture_black = NULL;
3915         r_texture_whitecube = NULL;
3916         r_texture_normalizationcube = NULL;
3917         r_texture_fogattenuation = NULL;
3918         r_texture_fogheighttexture = NULL;
3919         r_texture_gammaramps = NULL;
3920         r_texture_numcubemaps = 0;
3921         //r_texture_fogintensity = NULL;
3922         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3923         memset(&r_waterstate, 0, sizeof(r_waterstate));
3924         R_GLSL_Restart_f();
3925
3926         r_glsl_permutation = NULL;
3927         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3928         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3929         glslshaderstring = NULL;
3930 #ifdef SUPPORTD3D
3931         r_hlsl_permutation = NULL;
3932         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3933         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3934 #endif
3935         hlslshaderstring = NULL;
3936 }
3937
3938 extern void CL_ParseEntityLump(char *entitystring);
3939 void gl_main_newmap(void)
3940 {
3941         // FIXME: move this code to client
3942         char *entities, entname[MAX_QPATH];
3943         if (r_qwskincache)
3944                 Mem_Free(r_qwskincache);
3945         r_qwskincache = NULL;
3946         r_qwskincache_size = 0;
3947         if (cl.worldmodel)
3948         {
3949                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3950                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3951                 {
3952                         CL_ParseEntityLump(entities);
3953                         Mem_Free(entities);
3954                         return;
3955                 }
3956                 if (cl.worldmodel->brush.entities)
3957                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3958         }
3959         R_Main_FreeViewCache();
3960
3961         R_FrameData_Reset();
3962 }
3963
3964 void GL_Main_Init(void)
3965 {
3966         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3967
3968         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3969         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3970         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3971         if (gamemode == GAME_NEHAHRA)
3972         {
3973                 Cvar_RegisterVariable (&gl_fogenable);
3974                 Cvar_RegisterVariable (&gl_fogdensity);
3975                 Cvar_RegisterVariable (&gl_fogred);
3976                 Cvar_RegisterVariable (&gl_foggreen);
3977                 Cvar_RegisterVariable (&gl_fogblue);
3978                 Cvar_RegisterVariable (&gl_fogstart);
3979                 Cvar_RegisterVariable (&gl_fogend);
3980                 Cvar_RegisterVariable (&gl_skyclip);
3981         }
3982         Cvar_RegisterVariable(&r_motionblur);
3983         Cvar_RegisterVariable(&r_motionblur_maxblur);
3984         Cvar_RegisterVariable(&r_motionblur_bmin);
3985         Cvar_RegisterVariable(&r_motionblur_vmin);
3986         Cvar_RegisterVariable(&r_motionblur_vmax);
3987         Cvar_RegisterVariable(&r_motionblur_vcoeff);
3988         Cvar_RegisterVariable(&r_motionblur_randomize);
3989         Cvar_RegisterVariable(&r_damageblur);
3990         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3991         Cvar_RegisterVariable(&r_equalize_entities_minambient);
3992         Cvar_RegisterVariable(&r_equalize_entities_by);
3993         Cvar_RegisterVariable(&r_equalize_entities_to);
3994         Cvar_RegisterVariable(&r_depthfirst);
3995         Cvar_RegisterVariable(&r_useinfinitefarclip);
3996         Cvar_RegisterVariable(&r_farclip_base);
3997         Cvar_RegisterVariable(&r_farclip_world);
3998         Cvar_RegisterVariable(&r_nearclip);
3999         Cvar_RegisterVariable(&r_showbboxes);
4000         Cvar_RegisterVariable(&r_showsurfaces);
4001         Cvar_RegisterVariable(&r_showtris);
4002         Cvar_RegisterVariable(&r_shownormals);
4003         Cvar_RegisterVariable(&r_showlighting);
4004         Cvar_RegisterVariable(&r_showshadowvolumes);
4005         Cvar_RegisterVariable(&r_showcollisionbrushes);
4006         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4007         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4008         Cvar_RegisterVariable(&r_showdisabledepthtest);
4009         Cvar_RegisterVariable(&r_drawportals);
4010         Cvar_RegisterVariable(&r_drawentities);
4011         Cvar_RegisterVariable(&r_draw2d);
4012         Cvar_RegisterVariable(&r_drawworld);
4013         Cvar_RegisterVariable(&r_cullentities_trace);
4014         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4015         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4016         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4017         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4018         Cvar_RegisterVariable(&r_drawviewmodel);
4019         Cvar_RegisterVariable(&r_drawexteriormodel);
4020         Cvar_RegisterVariable(&r_speeds);
4021         Cvar_RegisterVariable(&r_fullbrights);
4022         Cvar_RegisterVariable(&r_wateralpha);
4023         Cvar_RegisterVariable(&r_dynamic);
4024         Cvar_RegisterVariable(&r_fakelight);
4025         Cvar_RegisterVariable(&r_fakelight_intensity);
4026         Cvar_RegisterVariable(&r_fullbright);
4027         Cvar_RegisterVariable(&r_shadows);
4028         Cvar_RegisterVariable(&r_shadows_darken);
4029         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4030         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4031         Cvar_RegisterVariable(&r_shadows_throwdistance);
4032         Cvar_RegisterVariable(&r_shadows_throwdirection);
4033         Cvar_RegisterVariable(&r_shadows_focus);
4034         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4035         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4036         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4037         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4038         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4039         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4040         Cvar_RegisterVariable(&r_fog_exp2);
4041         Cvar_RegisterVariable(&r_drawfog);
4042         Cvar_RegisterVariable(&r_transparentdepthmasking);
4043         Cvar_RegisterVariable(&r_texture_dds_load);
4044         Cvar_RegisterVariable(&r_texture_dds_save);
4045         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4046         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4047         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4048         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4049         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4050         Cvar_RegisterVariable(&r_textureunits);
4051         Cvar_RegisterVariable(&gl_combine);
4052         Cvar_RegisterVariable(&r_glsl);
4053         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4054         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4055         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4056         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4057         Cvar_RegisterVariable(&r_glsl_postprocess);
4058         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4059         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4060         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4061         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4062         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4063         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4064         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4065         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4066
4067         Cvar_RegisterVariable(&r_water);
4068         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4069         Cvar_RegisterVariable(&r_water_clippingplanebias);
4070         Cvar_RegisterVariable(&r_water_refractdistort);
4071         Cvar_RegisterVariable(&r_water_reflectdistort);
4072         Cvar_RegisterVariable(&r_water_scissormode);
4073         Cvar_RegisterVariable(&r_lerpsprites);
4074         Cvar_RegisterVariable(&r_lerpmodels);
4075         Cvar_RegisterVariable(&r_lerplightstyles);
4076         Cvar_RegisterVariable(&r_waterscroll);
4077         Cvar_RegisterVariable(&r_bloom);
4078         Cvar_RegisterVariable(&r_bloom_colorscale);
4079         Cvar_RegisterVariable(&r_bloom_brighten);
4080         Cvar_RegisterVariable(&r_bloom_blur);
4081         Cvar_RegisterVariable(&r_bloom_resolution);
4082         Cvar_RegisterVariable(&r_bloom_colorexponent);
4083         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4084         Cvar_RegisterVariable(&r_hdr);
4085         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4086         Cvar_RegisterVariable(&r_hdr_glowintensity);
4087         Cvar_RegisterVariable(&r_hdr_range);
4088         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4089         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4090         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4091         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4092         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4093         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4094         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4095         Cvar_RegisterVariable(&developer_texturelogging);
4096         Cvar_RegisterVariable(&gl_lightmaps);
4097         Cvar_RegisterVariable(&r_test);
4098         Cvar_RegisterVariable(&r_glsl_saturation);
4099         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4100         Cvar_RegisterVariable(&r_framedatasize);
4101         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4102                 Cvar_SetValue("r_fullbrights", 0);
4103         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4104
4105         Cvar_RegisterVariable(&r_track_sprites);
4106         Cvar_RegisterVariable(&r_track_sprites_flags);
4107         Cvar_RegisterVariable(&r_track_sprites_scalew);
4108         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4109         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4110         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4111         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4112         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4113 }
4114
4115 extern void R_Textures_Init(void);
4116 extern void GL_Draw_Init(void);
4117 extern void GL_Main_Init(void);
4118 extern void R_Shadow_Init(void);
4119 extern void R_Sky_Init(void);
4120 extern void GL_Surf_Init(void);
4121 extern void R_Particles_Init(void);
4122 extern void R_Explosion_Init(void);
4123 extern void gl_backend_init(void);
4124 extern void Sbar_Init(void);
4125 extern void R_LightningBeams_Init(void);
4126 extern void Mod_RenderInit(void);
4127 extern void Font_Init(void);
4128
4129 void Render_Init(void)
4130 {
4131         gl_backend_init();
4132         R_Textures_Init();
4133         GL_Main_Init();
4134         Font_Init();
4135         GL_Draw_Init();
4136         R_Shadow_Init();
4137         R_Sky_Init();
4138         GL_Surf_Init();
4139         Sbar_Init();
4140         R_Particles_Init();
4141         R_Explosion_Init();
4142         R_LightningBeams_Init();
4143         Mod_RenderInit();
4144 }
4145
4146 /*
4147 ===============
4148 GL_Init
4149 ===============
4150 */
4151 extern char *ENGINE_EXTENSIONS;
4152 void GL_Init (void)
4153 {
4154         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4155         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4156         gl_version = (const char *)qglGetString(GL_VERSION);
4157         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4158
4159         if (!gl_extensions)
4160                 gl_extensions = "";
4161         if (!gl_platformextensions)
4162                 gl_platformextensions = "";
4163
4164         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4165         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4166         Con_Printf("GL_VERSION: %s\n", gl_version);
4167         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4168         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4169
4170         VID_CheckExtensions();
4171
4172         // LordHavoc: report supported extensions
4173         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4174
4175         // clear to black (loading plaque will be seen over this)
4176         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4177 }
4178
4179 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4180 {
4181         int i;
4182         mplane_t *p;
4183         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4184         {
4185                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4186                 if (i == 4)
4187                         continue;
4188                 p = r_refdef.view.frustum + i;
4189                 switch(p->signbits)
4190                 {
4191                 default:
4192                 case 0:
4193                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4194                                 return true;
4195                         break;
4196                 case 1:
4197                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4198                                 return true;
4199                         break;
4200                 case 2:
4201                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4202                                 return true;
4203                         break;
4204                 case 3:
4205                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4206                                 return true;
4207                         break;
4208                 case 4:
4209                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4210                                 return true;
4211                         break;
4212                 case 5:
4213                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4214                                 return true;
4215                         break;
4216                 case 6:
4217                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4218                                 return true;
4219                         break;
4220                 case 7:
4221                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4222                                 return true;
4223                         break;
4224                 }
4225         }
4226         return false;
4227 }
4228
4229 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4230 {
4231         int i;
4232         const mplane_t *p;
4233         for (i = 0;i < numplanes;i++)
4234         {
4235                 p = planes + i;
4236                 switch(p->signbits)
4237                 {
4238                 default:
4239                 case 0:
4240                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4241                                 return true;
4242                         break;
4243                 case 1:
4244                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4245                                 return true;
4246                         break;
4247                 case 2:
4248                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4249                                 return true;
4250                         break;
4251                 case 3:
4252                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4253                                 return true;
4254                         break;
4255                 case 4:
4256                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4257                                 return true;
4258                         break;
4259                 case 5:
4260                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4261                                 return true;
4262                         break;
4263                 case 6:
4264                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4265                                 return true;
4266                         break;
4267                 case 7:
4268                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4269                                 return true;
4270                         break;
4271                 }
4272         }
4273         return false;
4274 }
4275
4276 //==================================================================================
4277
4278 // LordHavoc: this stores temporary data used within the same frame
4279
4280 typedef struct r_framedata_mem_s
4281 {
4282         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4283         size_t size; // how much usable space
4284         size_t current; // how much space in use
4285         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4286         size_t wantedsize; // how much space was allocated
4287         unsigned char *data; // start of real data (16byte aligned)
4288 }
4289 r_framedata_mem_t;
4290
4291 static r_framedata_mem_t *r_framedata_mem;
4292
4293 void R_FrameData_Reset(void)
4294 {
4295         while (r_framedata_mem)
4296         {
4297                 r_framedata_mem_t *next = r_framedata_mem->purge;
4298                 Mem_Free(r_framedata_mem);
4299                 r_framedata_mem = next;
4300         }
4301 }
4302
4303 void R_FrameData_Resize(void)
4304 {
4305         size_t wantedsize;
4306         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4307         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4308         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4309         {
4310                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4311                 newmem->wantedsize = wantedsize;
4312                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4313                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4314                 newmem->current = 0;
4315                 newmem->mark = 0;
4316                 newmem->purge = r_framedata_mem;
4317                 r_framedata_mem = newmem;
4318         }
4319 }
4320
4321 void R_FrameData_NewFrame(void)
4322 {
4323         R_FrameData_Resize();
4324         if (!r_framedata_mem)
4325                 return;
4326         // if we ran out of space on the last frame, free the old memory now
4327         while (r_framedata_mem->purge)
4328         {
4329                 // repeatedly remove the second item in the list, leaving only head
4330                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4331                 Mem_Free(r_framedata_mem->purge);
4332                 r_framedata_mem->purge = next;
4333         }
4334         // reset the current mem pointer
4335         r_framedata_mem->current = 0;
4336         r_framedata_mem->mark = 0;
4337 }
4338
4339 void *R_FrameData_Alloc(size_t size)
4340 {
4341         void *data;
4342
4343         // align to 16 byte boundary - the data pointer is already aligned, so we
4344         // only need to ensure the size of every allocation is also aligned
4345         size = (size + 15) & ~15;
4346
4347         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4348         {
4349                 // emergency - we ran out of space, allocate more memory
4350                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4351                 R_FrameData_Resize();
4352         }
4353
4354         data = r_framedata_mem->data + r_framedata_mem->current;
4355         r_framedata_mem->current += size;
4356
4357         // count the usage for stats
4358         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4359         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4360
4361         return (void *)data;
4362 }
4363
4364 void *R_FrameData_Store(size_t size, void *data)
4365 {
4366         void *d = R_FrameData_Alloc(size);
4367         if (d && data)
4368                 memcpy(d, data, size);
4369         return d;
4370 }
4371
4372 void R_FrameData_SetMark(void)
4373 {
4374         if (!r_framedata_mem)
4375                 return;
4376         r_framedata_mem->mark = r_framedata_mem->current;
4377 }
4378
4379 void R_FrameData_ReturnToMark(void)
4380 {
4381         if (!r_framedata_mem)
4382                 return;
4383         r_framedata_mem->current = r_framedata_mem->mark;
4384 }
4385
4386 //==================================================================================
4387
4388 // LordHavoc: animcache originally written by Echon, rewritten since then
4389
4390 /**
4391  * Animation cache prevents re-generating mesh data for an animated model
4392  * multiple times in one frame for lighting, shadowing, reflections, etc.
4393  */
4394
4395 void R_AnimCache_Free(void)
4396 {
4397 }
4398
4399 void R_AnimCache_ClearCache(void)
4400 {
4401         int i;
4402         entity_render_t *ent;
4403
4404         for (i = 0;i < r_refdef.scene.numentities;i++)
4405         {
4406                 ent = r_refdef.scene.entities[i];
4407                 ent->animcache_vertex3f = NULL;
4408                 ent->animcache_normal3f = NULL;
4409                 ent->animcache_svector3f = NULL;
4410                 ent->animcache_tvector3f = NULL;
4411                 ent->animcache_vertexmesh = NULL;
4412                 ent->animcache_vertex3fbuffer = NULL;
4413                 ent->animcache_vertexmeshbuffer = NULL;
4414         }
4415 }
4416
4417 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4418 {
4419         int i;
4420
4421         // check if we need the meshbuffers
4422         if (!vid.useinterleavedarrays)
4423                 return;
4424
4425         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4426                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4427         // TODO: upload vertex3f buffer?
4428         if (ent->animcache_vertexmesh)
4429         {
4430                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4431                 for (i = 0;i < numvertices;i++)
4432                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4433                 if (ent->animcache_svector3f)
4434                         for (i = 0;i < numvertices;i++)
4435                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4436                 if (ent->animcache_tvector3f)
4437                         for (i = 0;i < numvertices;i++)
4438                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4439                 if (ent->animcache_normal3f)
4440                         for (i = 0;i < numvertices;i++)
4441                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4442                 // TODO: upload vertexmeshbuffer?
4443         }
4444 }
4445
4446 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4447 {
4448         dp_model_t *model = ent->model;
4449         int numvertices;
4450         // see if it's already cached this frame
4451         if (ent->animcache_vertex3f)
4452         {
4453                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4454                 if (wantnormals || wanttangents)
4455                 {
4456                         if (ent->animcache_normal3f)
4457                                 wantnormals = false;
4458                         if (ent->animcache_svector3f)
4459                                 wanttangents = false;
4460                         if (wantnormals || wanttangents)
4461                         {
4462                                 numvertices = model->surfmesh.num_vertices;
4463                                 if (wantnormals)
4464                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4465                                 if (wanttangents)
4466                                 {
4467                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4468                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4469                                 }
4470                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4471                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4472                         }
4473                 }
4474         }
4475         else
4476         {
4477                 // see if this ent is worth caching
4478                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4479                         return false;
4480                 // get some memory for this entity and generate mesh data
4481                 numvertices = model->surfmesh.num_vertices;
4482                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4483                 if (wantnormals)
4484                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4485                 if (wanttangents)
4486                 {
4487                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4488                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4489                 }
4490                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4491                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4492         }
4493         return true;
4494 }
4495
4496 void R_AnimCache_CacheVisibleEntities(void)
4497 {
4498         int i;
4499         qboolean wantnormals = true;
4500         qboolean wanttangents = !r_showsurfaces.integer;
4501
4502         switch(vid.renderpath)
4503         {
4504         case RENDERPATH_GL20:
4505         case RENDERPATH_D3D9:
4506         case RENDERPATH_D3D10:
4507         case RENDERPATH_D3D11:
4508         case RENDERPATH_GLES2:
4509                 break;
4510         case RENDERPATH_GL13:
4511         case RENDERPATH_GL11:
4512                 wanttangents = false;
4513                 break;
4514         case RENDERPATH_SOFT:
4515                 break;
4516         }
4517
4518         if (r_shownormals.integer)
4519                 wanttangents = wantnormals = true;
4520
4521         // TODO: thread this
4522         // NOTE: R_PrepareRTLights() also caches entities
4523
4524         for (i = 0;i < r_refdef.scene.numentities;i++)
4525                 if (r_refdef.viewcache.entityvisible[i])
4526                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4527 }
4528
4529 //==================================================================================
4530
4531 static void R_View_UpdateEntityLighting (void)
4532 {
4533         int i;
4534         entity_render_t *ent;
4535         vec3_t tempdiffusenormal, avg;
4536         vec_t f, fa, fd, fdd;
4537         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4538
4539         for (i = 0;i < r_refdef.scene.numentities;i++)
4540         {
4541                 ent = r_refdef.scene.entities[i];
4542
4543                 // skip unseen models
4544                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4545                         continue;
4546
4547                 // skip bsp models
4548                 if (ent->model && ent->model->brush.num_leafs)
4549                 {
4550                         // TODO: use modellight for r_ambient settings on world?
4551                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4552                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4553                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4554                         continue;
4555                 }
4556
4557                 // fetch the lighting from the worldmodel data
4558                 VectorClear(ent->modellight_ambient);
4559                 VectorClear(ent->modellight_diffuse);
4560                 VectorClear(tempdiffusenormal);
4561                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4562                 {
4563                         vec3_t org;
4564                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4565
4566                         // complete lightning for lit sprites
4567                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4568                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4569                         {
4570                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4571                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4572                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4573                         }
4574                         else
4575                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4576
4577                         if(ent->flags & RENDER_EQUALIZE)
4578                         {
4579                                 // first fix up ambient lighting...
4580                                 if(r_equalize_entities_minambient.value > 0)
4581                                 {
4582                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4583                                         if(fd > 0)
4584                                         {
4585                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4586                                                 if(fa < r_equalize_entities_minambient.value * fd)
4587                                                 {
4588                                                         // solve:
4589                                                         //   fa'/fd' = minambient
4590                                                         //   fa'+0.25*fd' = fa+0.25*fd
4591                                                         //   ...
4592                                                         //   fa' = fd' * minambient
4593                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4594                                                         //   ...
4595                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4596                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4597                                                         //   ...
4598                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4599                                                         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
4600                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4601                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4602                                                 }
4603                                         }
4604                                 }
4605
4606                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4607                                 {
4608                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4609                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4610                                         f = fa + 0.25 * fd;
4611                                         if(f > 0)
4612                                         {
4613                                                 // adjust brightness and saturation to target
4614                                                 avg[0] = avg[1] = avg[2] = fa / f;
4615                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4616                                                 avg[0] = avg[1] = avg[2] = fd / f;
4617                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4618                                         }
4619                                 }
4620                         }
4621                 }
4622                 else // highly rare
4623                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4624
4625                 // move the light direction into modelspace coordinates for lighting code
4626                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4627                 if(VectorLength2(ent->modellight_lightdir) == 0)
4628                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4629                 VectorNormalize(ent->modellight_lightdir);
4630         }
4631 }
4632
4633 #define MAX_LINEOFSIGHTTRACES 64
4634
4635 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4636 {
4637         int i;
4638         vec3_t boxmins, boxmaxs;
4639         vec3_t start;
4640         vec3_t end;
4641         dp_model_t *model = r_refdef.scene.worldmodel;
4642
4643         if (!model || !model->brush.TraceLineOfSight)
4644                 return true;
4645
4646         // expand the box a little
4647         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4648         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4649         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4650         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4651         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4652         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4653
4654         // return true if eye is inside enlarged box
4655         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4656                 return true;
4657
4658         // try center
4659         VectorCopy(eye, start);
4660         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4661         if (model->brush.TraceLineOfSight(model, start, end))
4662                 return true;
4663
4664         // try various random positions
4665         for (i = 0;i < numsamples;i++)
4666         {
4667                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4668                 if (model->brush.TraceLineOfSight(model, start, end))
4669                         return true;
4670         }
4671
4672         return false;
4673 }
4674
4675
4676 static void R_View_UpdateEntityVisible (void)
4677 {
4678         int i;
4679         int renderimask;
4680         int samples;
4681         entity_render_t *ent;
4682
4683         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4684                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4685                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4686                 :                                                          RENDER_EXTERIORMODEL;
4687         if (!r_drawviewmodel.integer)
4688                 renderimask |= RENDER_VIEWMODEL;
4689         if (!r_drawexteriormodel.integer)
4690                 renderimask |= RENDER_EXTERIORMODEL;
4691         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4692         {
4693                 // worldmodel can check visibility
4694                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4695                 for (i = 0;i < r_refdef.scene.numentities;i++)
4696                 {
4697                         ent = r_refdef.scene.entities[i];
4698                         if (!(ent->flags & renderimask))
4699                         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)))
4700                         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))
4701                                 r_refdef.viewcache.entityvisible[i] = true;
4702                 }
4703                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4704                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4705                 {
4706                         for (i = 0;i < r_refdef.scene.numentities;i++)
4707                         {
4708                                 ent = r_refdef.scene.entities[i];
4709                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4710                                 {
4711                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4712                                         if (samples < 0)
4713                                                 continue; // temp entities do pvs only
4714                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4715                                                 ent->last_trace_visibility = realtime;
4716                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4717                                                 r_refdef.viewcache.entityvisible[i] = 0;
4718                                 }
4719                         }
4720                 }
4721         }
4722         else
4723         {
4724                 // no worldmodel or it can't check visibility
4725                 for (i = 0;i < r_refdef.scene.numentities;i++)
4726                 {
4727                         ent = r_refdef.scene.entities[i];
4728                         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));
4729                 }
4730         }
4731 }
4732
4733 /// only used if skyrendermasked, and normally returns false
4734 int R_DrawBrushModelsSky (void)
4735 {
4736         int i, sky;
4737         entity_render_t *ent;
4738
4739         sky = false;
4740         for (i = 0;i < r_refdef.scene.numentities;i++)
4741         {
4742                 if (!r_refdef.viewcache.entityvisible[i])
4743                         continue;
4744                 ent = r_refdef.scene.entities[i];
4745                 if (!ent->model || !ent->model->DrawSky)
4746                         continue;
4747                 ent->model->DrawSky(ent);
4748                 sky = true;
4749         }
4750         return sky;
4751 }
4752
4753 static void R_DrawNoModel(entity_render_t *ent);
4754 static void R_DrawModels(void)
4755 {
4756         int i;
4757         entity_render_t *ent;
4758
4759         for (i = 0;i < r_refdef.scene.numentities;i++)
4760         {
4761                 if (!r_refdef.viewcache.entityvisible[i])
4762                         continue;
4763                 ent = r_refdef.scene.entities[i];
4764                 r_refdef.stats.entities++;
4765                 if (ent->model && ent->model->Draw != NULL)
4766                         ent->model->Draw(ent);
4767                 else
4768                         R_DrawNoModel(ent);
4769         }
4770 }
4771
4772 static void R_DrawModelsDepth(void)
4773 {
4774         int i;
4775         entity_render_t *ent;
4776
4777         for (i = 0;i < r_refdef.scene.numentities;i++)
4778         {
4779                 if (!r_refdef.viewcache.entityvisible[i])
4780                         continue;
4781                 ent = r_refdef.scene.entities[i];
4782                 if (ent->model && ent->model->DrawDepth != NULL)
4783                         ent->model->DrawDepth(ent);
4784         }
4785 }
4786
4787 static void R_DrawModelsDebug(void)
4788 {
4789         int i;
4790         entity_render_t *ent;
4791
4792         for (i = 0;i < r_refdef.scene.numentities;i++)
4793         {
4794                 if (!r_refdef.viewcache.entityvisible[i])
4795                         continue;
4796                 ent = r_refdef.scene.entities[i];
4797                 if (ent->model && ent->model->DrawDebug != NULL)
4798                         ent->model->DrawDebug(ent);
4799         }
4800 }
4801
4802 static void R_DrawModelsAddWaterPlanes(void)
4803 {
4804         int i;
4805         entity_render_t *ent;
4806
4807         for (i = 0;i < r_refdef.scene.numentities;i++)
4808         {
4809                 if (!r_refdef.viewcache.entityvisible[i])
4810                         continue;
4811                 ent = r_refdef.scene.entities[i];
4812                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4813                         ent->model->DrawAddWaterPlanes(ent);
4814         }
4815 }
4816
4817 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4818 {
4819         if (r_hdr_irisadaptation.integer)
4820         {
4821                 vec3_t ambient;
4822                 vec3_t diffuse;
4823                 vec3_t diffusenormal;
4824                 vec_t brightness;
4825                 vec_t goal;
4826                 vec_t adjust;
4827                 vec_t current;
4828                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4829                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4830                 brightness = max(0.0000001f, brightness);
4831                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4832                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4833                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4834                 current = r_hdr_irisadaptation_value.value;
4835                 if (current < goal)
4836                         current = min(current + adjust, goal);
4837                 else if (current > goal)
4838                         current = max(current - adjust, goal);
4839                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4840                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4841         }
4842         else if (r_hdr_irisadaptation_value.value != 1.0f)
4843                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4844 }
4845
4846 static void R_View_SetFrustum(const int *scissor)
4847 {
4848         int i;
4849         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4850         vec3_t forward, left, up, origin, v;
4851
4852         if(scissor)
4853         {
4854                 // flipped x coordinates (because x points left here)
4855                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4856                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4857
4858                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4859                 switch(vid.renderpath)
4860                 {
4861                         case RENDERPATH_D3D9:
4862                         case RENDERPATH_D3D10:
4863                         case RENDERPATH_D3D11:
4864                         case RENDERPATH_SOFT:
4865                                 // non-flipped y coordinates
4866                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4867                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4868                                 break;
4869                         case RENDERPATH_GL11:
4870                         case RENDERPATH_GL13:
4871                         case RENDERPATH_GL20:
4872                         case RENDERPATH_GLES2:
4873                                 // non-flipped y coordinates
4874                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4875                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4876                                 break;
4877                 }
4878         }
4879
4880         // we can't trust r_refdef.view.forward and friends in reflected scenes
4881         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4882
4883 #if 0
4884         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4885         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4886         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4887         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4888         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4889         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4890         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4891         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4892         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4893         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4894         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4895         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4896 #endif
4897
4898 #if 0
4899         zNear = r_refdef.nearclip;
4900         nudge = 1.0 - 1.0 / (1<<23);
4901         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4902         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4903         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4904         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4905         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4906         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4907         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4908         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4909 #endif
4910
4911
4912
4913 #if 0
4914         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4915         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4916         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4917         r_refdef.view.frustum[0].dist = m[15] - m[12];
4918
4919         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4920         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4921         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4922         r_refdef.view.frustum[1].dist = m[15] + m[12];
4923
4924         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4925         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4926         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4927         r_refdef.view.frustum[2].dist = m[15] - m[13];
4928
4929         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4930         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4931         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4932         r_refdef.view.frustum[3].dist = m[15] + m[13];
4933
4934         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4935         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4936         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4937         r_refdef.view.frustum[4].dist = m[15] - m[14];
4938
4939         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4940         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4941         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4942         r_refdef.view.frustum[5].dist = m[15] + m[14];
4943 #endif
4944
4945         if (r_refdef.view.useperspective)
4946         {
4947                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4948                 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]);
4949                 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]);
4950                 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]);
4951                 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]);
4952
4953                 // then the normals from the corners relative to origin
4954                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4955                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4956                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4957                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4958
4959                 // in a NORMAL view, forward cross left == up
4960                 // in a REFLECTED view, forward cross left == down
4961                 // so our cross products above need to be adjusted for a left handed coordinate system
4962                 CrossProduct(forward, left, v);
4963                 if(DotProduct(v, up) < 0)
4964                 {
4965                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4966                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
4967                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
4968                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
4969                 }
4970
4971                 // Leaving those out was a mistake, those were in the old code, and they
4972                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4973                 // I couldn't reproduce it after adding those normalizations. --blub
4974                 VectorNormalize(r_refdef.view.frustum[0].normal);
4975                 VectorNormalize(r_refdef.view.frustum[1].normal);
4976                 VectorNormalize(r_refdef.view.frustum[2].normal);
4977                 VectorNormalize(r_refdef.view.frustum[3].normal);
4978
4979                 // make the corners absolute
4980                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
4981                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
4982                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
4983                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
4984
4985                 // one more normal
4986                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4987
4988                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4989                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4990                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4991                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4992                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4993         }
4994         else
4995         {
4996                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
4997                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
4998                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
4999                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5000                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5001                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5002                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5003                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5004                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5005                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5006         }
5007         r_refdef.view.numfrustumplanes = 5;
5008
5009         if (r_refdef.view.useclipplane)
5010         {
5011                 r_refdef.view.numfrustumplanes = 6;
5012                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5013         }
5014
5015         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5016                 PlaneClassify(r_refdef.view.frustum + i);
5017
5018         // LordHavoc: note to all quake engine coders, Quake had a special case
5019         // for 90 degrees which assumed a square view (wrong), so I removed it,
5020         // Quake2 has it disabled as well.
5021
5022         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5023         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5024         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5025         //PlaneClassify(&frustum[0]);
5026
5027         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5028         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5029         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5030         //PlaneClassify(&frustum[1]);
5031
5032         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5033         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5034         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5035         //PlaneClassify(&frustum[2]);
5036
5037         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5038         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5039         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5040         //PlaneClassify(&frustum[3]);
5041
5042         // nearclip plane
5043         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5044         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5045         //PlaneClassify(&frustum[4]);
5046 }
5047
5048 void R_View_UpdateWithScissor(const int *myscissor)
5049 {
5050         R_Main_ResizeViewCache();
5051         R_View_SetFrustum(myscissor);
5052         R_View_WorldVisibility(r_refdef.view.useclipplane);
5053         R_View_UpdateEntityVisible();
5054         R_View_UpdateEntityLighting();
5055 }
5056
5057 void R_View_Update(void)
5058 {
5059         R_Main_ResizeViewCache();
5060         R_View_SetFrustum(NULL);
5061         R_View_WorldVisibility(r_refdef.view.useclipplane);
5062         R_View_UpdateEntityVisible();
5063         R_View_UpdateEntityLighting();
5064 }
5065
5066 void R_SetupView(qboolean allowwaterclippingplane)
5067 {
5068         const float *customclipplane = NULL;
5069         float plane[4];
5070         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5071         {
5072                 // LordHavoc: couldn't figure out how to make this approach the
5073                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5074                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5075                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5076                         dist = r_refdef.view.clipplane.dist;
5077                 plane[0] = r_refdef.view.clipplane.normal[0];
5078                 plane[1] = r_refdef.view.clipplane.normal[1];
5079                 plane[2] = r_refdef.view.clipplane.normal[2];
5080                 plane[3] = dist;
5081                 customclipplane = plane;
5082         }
5083
5084         if (!r_refdef.view.useperspective)
5085                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -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);
5086         else if (vid.stencil && r_useinfinitefarclip.integer)
5087                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5088         else
5089                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5090         R_SetViewport(&r_refdef.view.viewport);
5091 }
5092
5093 void R_EntityMatrix(const matrix4x4_t *matrix)
5094 {
5095         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5096         {
5097                 gl_modelmatrixchanged = false;
5098                 gl_modelmatrix = *matrix;
5099                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5100                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5101                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5102                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5103                 CHECKGLERROR
5104                 switch(vid.renderpath)
5105                 {
5106                 case RENDERPATH_D3D9:
5107 #ifdef SUPPORTD3D
5108                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5109                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5110 #endif
5111                         break;
5112                 case RENDERPATH_D3D10:
5113                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5114                         break;
5115                 case RENDERPATH_D3D11:
5116                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5117                         break;
5118                 case RENDERPATH_GL13:
5119                 case RENDERPATH_GL11:
5120                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5121                         break;
5122                 case RENDERPATH_SOFT:
5123                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5124                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5125                         break;
5126                 case RENDERPATH_GL20:
5127                 case RENDERPATH_GLES2:
5128                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5129                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5130                         break;
5131                 }
5132         }
5133 }
5134
5135 void R_ResetViewRendering2D(void)
5136 {
5137         r_viewport_t viewport;
5138         DrawQ_Finish();
5139
5140         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5141         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);
5142         R_SetViewport(&viewport);
5143         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5144         GL_Color(1, 1, 1, 1);
5145         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5146         GL_BlendFunc(GL_ONE, GL_ZERO);
5147         GL_ScissorTest(false);
5148         GL_DepthMask(false);
5149         GL_DepthRange(0, 1);
5150         GL_DepthTest(false);
5151         GL_DepthFunc(GL_LEQUAL);
5152         R_EntityMatrix(&identitymatrix);
5153         R_Mesh_ResetTextureState();
5154         GL_PolygonOffset(0, 0);
5155         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5156         switch(vid.renderpath)
5157         {
5158         case RENDERPATH_GL11:
5159         case RENDERPATH_GL13:
5160         case RENDERPATH_GL20:
5161         case RENDERPATH_GLES2:
5162                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5163                 break;
5164         case RENDERPATH_D3D9:
5165         case RENDERPATH_D3D10:
5166         case RENDERPATH_D3D11:
5167         case RENDERPATH_SOFT:
5168                 break;
5169         }
5170         GL_CullFace(GL_NONE);
5171 }
5172
5173 void R_ResetViewRendering3D(void)
5174 {
5175         DrawQ_Finish();
5176
5177         R_SetupView(true);
5178         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5179         GL_Color(1, 1, 1, 1);
5180         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5181         GL_BlendFunc(GL_ONE, GL_ZERO);
5182         GL_ScissorTest(true);
5183         GL_DepthMask(true);
5184         GL_DepthRange(0, 1);
5185         GL_DepthTest(true);
5186         GL_DepthFunc(GL_LEQUAL);
5187         R_EntityMatrix(&identitymatrix);
5188         R_Mesh_ResetTextureState();
5189         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5190         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5191         switch(vid.renderpath)
5192         {
5193         case RENDERPATH_GL11:
5194         case RENDERPATH_GL13:
5195         case RENDERPATH_GL20:
5196         case RENDERPATH_GLES2:
5197                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5198                 break;
5199         case RENDERPATH_D3D9:
5200         case RENDERPATH_D3D10:
5201         case RENDERPATH_D3D11:
5202         case RENDERPATH_SOFT:
5203                 break;
5204         }
5205         GL_CullFace(r_refdef.view.cullface_back);
5206 }
5207
5208 /*
5209 ================
5210 R_RenderView_UpdateViewVectors
5211 ================
5212 */
5213 static void R_RenderView_UpdateViewVectors(void)
5214 {
5215         // break apart the view matrix into vectors for various purposes
5216         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5217         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5218         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5219         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5220         // make an inverted copy of the view matrix for tracking sprites
5221         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5222 }
5223
5224 void R_RenderScene(void);
5225 void R_RenderWaterPlanes(void);
5226
5227 static void R_Water_StartFrame(void)
5228 {
5229         int i;
5230         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5231         r_waterstate_waterplane_t *p;
5232
5233         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5234                 return;
5235
5236         switch(vid.renderpath)
5237         {
5238         case RENDERPATH_GL20:
5239         case RENDERPATH_D3D9:
5240         case RENDERPATH_D3D10:
5241         case RENDERPATH_D3D11:
5242         case RENDERPATH_SOFT:
5243         case RENDERPATH_GLES2:
5244                 break;
5245         case RENDERPATH_GL13:
5246         case RENDERPATH_GL11:
5247                 return;
5248         }
5249
5250         // set waterwidth and waterheight to the water resolution that will be
5251         // used (often less than the screen resolution for faster rendering)
5252         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5253         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5254
5255         // calculate desired texture sizes
5256         // can't use water if the card does not support the texture size
5257         if (!r_water.integer || r_showsurfaces.integer)
5258                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5259         else if (vid.support.arb_texture_non_power_of_two)
5260         {
5261                 texturewidth = waterwidth;
5262                 textureheight = waterheight;
5263                 camerawidth = waterwidth;
5264                 cameraheight = waterheight;
5265         }
5266         else
5267         {
5268                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5269                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5270                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5271                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5272         }
5273
5274         // allocate textures as needed
5275         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5276         {
5277                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5278                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5279                 {
5280                         if (p->texture_refraction)
5281                                 R_FreeTexture(p->texture_refraction);
5282                         p->texture_refraction = NULL;
5283                         if (p->texture_reflection)
5284                                 R_FreeTexture(p->texture_reflection);
5285                         p->texture_reflection = NULL;
5286                         if (p->texture_camera)
5287                                 R_FreeTexture(p->texture_camera);
5288                         p->texture_camera = NULL;
5289                 }
5290                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5291                 r_waterstate.texturewidth = texturewidth;
5292                 r_waterstate.textureheight = textureheight;
5293                 r_waterstate.camerawidth = camerawidth;
5294                 r_waterstate.cameraheight = cameraheight;
5295         }
5296
5297         if (r_waterstate.texturewidth)
5298         {
5299                 r_waterstate.enabled = true;
5300
5301                 // when doing a reduced render (HDR) we want to use a smaller area
5302                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5303                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5304
5305                 // set up variables that will be used in shader setup
5306                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5307                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5308                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5309                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5310         }
5311
5312         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5313         r_waterstate.numwaterplanes = 0;
5314 }
5315
5316 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5317 {
5318         int triangleindex, planeindex;
5319         const int *e;
5320         vec3_t vert[3];
5321         vec3_t normal;
5322         vec3_t center;
5323         mplane_t plane;
5324         r_waterstate_waterplane_t *p;
5325         texture_t *t = R_GetCurrentTexture(surface->texture);
5326
5327         // just use the first triangle with a valid normal for any decisions
5328         VectorClear(normal);
5329         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5330         {
5331                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5332                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5333                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5334                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5335                 if (VectorLength2(normal) >= 0.001)
5336                         break;
5337         }
5338
5339         VectorCopy(normal, plane.normal);
5340         VectorNormalize(plane.normal);
5341         plane.dist = DotProduct(vert[0], plane.normal);
5342         PlaneClassify(&plane);
5343         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5344         {
5345                 // skip backfaces (except if nocullface is set)
5346                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5347                         return;
5348                 VectorNegate(plane.normal, plane.normal);
5349                 plane.dist *= -1;
5350                 PlaneClassify(&plane);
5351         }
5352
5353
5354         // find a matching plane if there is one
5355         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5356                 if(p->camera_entity == t->camera_entity)
5357                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5358                                 break;
5359         if (planeindex >= r_waterstate.maxwaterplanes)
5360                 return; // nothing we can do, out of planes
5361
5362         // if this triangle does not fit any known plane rendered this frame, add one
5363         if (planeindex >= r_waterstate.numwaterplanes)
5364         {
5365                 // store the new plane
5366                 r_waterstate.numwaterplanes++;
5367                 p->plane = plane;
5368                 // clear materialflags and pvs
5369                 p->materialflags = 0;
5370                 p->pvsvalid = false;
5371                 p->camera_entity = t->camera_entity;
5372                 VectorCopy(surface->mins, p->mins);
5373                 VectorCopy(surface->maxs, p->maxs);
5374         }
5375         else
5376         {
5377                 // merge mins/maxs
5378                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5379                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5380                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5381                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5382                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5383                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5384         }
5385         // merge this surface's materialflags into the waterplane
5386         p->materialflags |= t->currentmaterialflags;
5387         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5388         {
5389                 // merge this surface's PVS into the waterplane
5390                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5391                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5392                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5393                 {
5394                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5395                         p->pvsvalid = true;
5396                 }
5397         }
5398 }
5399
5400 static void R_Water_ProcessPlanes(void)
5401 {
5402         int myscissor[4];
5403         r_refdef_view_t originalview;
5404         r_refdef_view_t myview;
5405         int planeindex;
5406         r_waterstate_waterplane_t *p;
5407         vec3_t visorigin;
5408
5409         originalview = r_refdef.view;
5410
5411         // make sure enough textures are allocated
5412         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5413         {
5414                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5415                 {
5416                         if (!p->texture_refraction)
5417                                 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);
5418                         if (!p->texture_refraction)
5419                                 goto error;
5420                 }
5421                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5422                 {
5423                         if (!p->texture_camera)
5424                                 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);
5425                         if (!p->texture_camera)
5426                                 goto error;
5427                 }
5428
5429                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5430                 {
5431                         if (!p->texture_reflection)
5432                                 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);
5433                         if (!p->texture_reflection)
5434                                 goto error;
5435                 }
5436         }
5437
5438         // render views
5439         r_refdef.view = originalview;
5440         r_refdef.view.showdebug = false;
5441         r_refdef.view.width = r_waterstate.waterwidth;
5442         r_refdef.view.height = r_waterstate.waterheight;
5443         r_refdef.view.useclipplane = true;
5444         myview = r_refdef.view;
5445         r_waterstate.renderingscene = true;
5446         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5447         {
5448                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5449                 {
5450                         r_refdef.view = myview;
5451                         if(r_water_scissormode.integer)
5452                         {
5453                                 R_SetupView(true);
5454                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5455                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5456                         }
5457
5458                         // render reflected scene and copy into texture
5459                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5460                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5461                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5462                         r_refdef.view.clipplane = p->plane;
5463
5464                         // reverse the cullface settings for this render
5465                         r_refdef.view.cullface_front = GL_FRONT;
5466                         r_refdef.view.cullface_back = GL_BACK;
5467                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5468                         {
5469                                 r_refdef.view.usecustompvs = true;
5470                                 if (p->pvsvalid)
5471                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5472                                 else
5473                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5474                         }
5475
5476                         R_ResetViewRendering3D();
5477                         R_ClearScreen(r_refdef.fogenabled);
5478                         if(r_water_scissormode.integer & 2)
5479                                 R_View_UpdateWithScissor(myscissor);
5480                         else
5481                                 R_View_Update();
5482                         if(r_water_scissormode.integer & 1)
5483                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5484                         R_RenderScene();
5485
5486                         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);
5487                 }
5488
5489                 // render the normal view scene and copy into texture
5490                 // (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)
5491                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5492                 {
5493                         r_refdef.view = myview;
5494                         if(r_water_scissormode.integer)
5495                         {
5496                                 R_SetupView(true);
5497                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5498                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5499                         }
5500
5501                         r_waterstate.renderingrefraction = true;
5502
5503                         r_refdef.view.clipplane = p->plane;
5504                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5505                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5506
5507                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5508                         {
5509                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5510                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5511                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5512                                 R_RenderView_UpdateViewVectors();
5513                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5514                                 {
5515                                         r_refdef.view.usecustompvs = true;
5516                                         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);
5517                                 }
5518                         }
5519
5520                         PlaneClassify(&r_refdef.view.clipplane);
5521
5522                         R_ResetViewRendering3D();
5523                         R_ClearScreen(r_refdef.fogenabled);
5524                         if(r_water_scissormode.integer & 2)
5525                                 R_View_UpdateWithScissor(myscissor);
5526                         else
5527                                 R_View_Update();
5528                         if(r_water_scissormode.integer & 1)
5529                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5530                         R_RenderScene();
5531
5532                         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);
5533                         r_waterstate.renderingrefraction = false;
5534                 }
5535                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5536                 {
5537                         r_refdef.view = myview;
5538
5539                         r_refdef.view.clipplane = p->plane;
5540                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5541                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5542
5543                         r_refdef.view.width = r_waterstate.camerawidth;
5544                         r_refdef.view.height = r_waterstate.cameraheight;
5545                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5546                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5547
5548                         if(p->camera_entity)
5549                         {
5550                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5551                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5552                         }
5553
5554                         // note: all of the view is used for displaying... so
5555                         // there is no use in scissoring
5556
5557                         // reverse the cullface settings for this render
5558                         r_refdef.view.cullface_front = GL_FRONT;
5559                         r_refdef.view.cullface_back = GL_BACK;
5560                         // also reverse the view matrix
5561                         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
5562                         R_RenderView_UpdateViewVectors();
5563                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5564                         {
5565                                 r_refdef.view.usecustompvs = true;
5566                                 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);
5567                         }
5568                         
5569                         // camera needs no clipplane
5570                         r_refdef.view.useclipplane = false;
5571
5572                         PlaneClassify(&r_refdef.view.clipplane);
5573
5574                         R_ResetViewRendering3D();
5575                         R_ClearScreen(r_refdef.fogenabled);
5576                         R_View_Update();
5577                         R_RenderScene();
5578
5579                         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);
5580                         r_waterstate.renderingrefraction = false;
5581                 }
5582
5583         }
5584         r_waterstate.renderingscene = false;
5585         r_refdef.view = originalview;
5586         R_ResetViewRendering3D();
5587         R_ClearScreen(r_refdef.fogenabled);
5588         R_View_Update();
5589         return;
5590 error:
5591         r_refdef.view = originalview;
5592         r_waterstate.renderingscene = false;
5593         Cvar_SetValueQuick(&r_water, 0);
5594         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5595         return;
5596 }
5597
5598 void R_Bloom_StartFrame(void)
5599 {
5600         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5601
5602         switch(vid.renderpath)
5603         {
5604         case RENDERPATH_GL20:
5605         case RENDERPATH_D3D9:
5606         case RENDERPATH_D3D10:
5607         case RENDERPATH_D3D11:
5608         case RENDERPATH_SOFT:
5609         case RENDERPATH_GLES2:
5610                 break;
5611         case RENDERPATH_GL13:
5612         case RENDERPATH_GL11:
5613                 return;
5614         }
5615
5616         // set bloomwidth and bloomheight to the bloom resolution that will be
5617         // used (often less than the screen resolution for faster rendering)
5618         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5619         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5620         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5621         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5622         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5623
5624         // calculate desired texture sizes
5625         if (vid.support.arb_texture_non_power_of_two)
5626         {
5627                 screentexturewidth = r_refdef.view.width;
5628                 screentextureheight = r_refdef.view.height;
5629                 bloomtexturewidth = r_bloomstate.bloomwidth;
5630                 bloomtextureheight = r_bloomstate.bloomheight;
5631         }
5632         else
5633         {
5634                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5635                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5636                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5637                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5638         }
5639
5640         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))
5641         {
5642                 Cvar_SetValueQuick(&r_hdr, 0);
5643                 Cvar_SetValueQuick(&r_bloom, 0);
5644                 Cvar_SetValueQuick(&r_motionblur, 0);
5645                 Cvar_SetValueQuick(&r_damageblur, 0);
5646         }
5647
5648         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)))
5649                 screentexturewidth = screentextureheight = 0;
5650         if (!r_hdr.integer && !r_bloom.integer)
5651                 bloomtexturewidth = bloomtextureheight = 0;
5652
5653         // allocate textures as needed
5654         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5655         {
5656                 if (r_bloomstate.texture_screen)
5657                         R_FreeTexture(r_bloomstate.texture_screen);
5658                 r_bloomstate.texture_screen = NULL;
5659                 r_bloomstate.screentexturewidth = screentexturewidth;
5660                 r_bloomstate.screentextureheight = screentextureheight;
5661                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5662                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
5663         }
5664         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5665         {
5666                 if (r_bloomstate.texture_bloom)
5667                         R_FreeTexture(r_bloomstate.texture_bloom);
5668                 r_bloomstate.texture_bloom = NULL;
5669                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5670                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5671                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5672                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5673         }
5674
5675         // when doing a reduced render (HDR) we want to use a smaller area
5676         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5677         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5678         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5679         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5680         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5681
5682         // set up a texcoord array for the full resolution screen image
5683         // (we have to keep this around to copy back during final render)
5684         r_bloomstate.screentexcoord2f[0] = 0;
5685         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5686         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5687         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5688         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5689         r_bloomstate.screentexcoord2f[5] = 0;
5690         r_bloomstate.screentexcoord2f[6] = 0;
5691         r_bloomstate.screentexcoord2f[7] = 0;
5692
5693         // set up a texcoord array for the reduced resolution bloom image
5694         // (which will be additive blended over the screen image)
5695         r_bloomstate.bloomtexcoord2f[0] = 0;
5696         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5697         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5698         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5699         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5700         r_bloomstate.bloomtexcoord2f[5] = 0;
5701         r_bloomstate.bloomtexcoord2f[6] = 0;
5702         r_bloomstate.bloomtexcoord2f[7] = 0;
5703
5704         switch(vid.renderpath)
5705         {
5706         case RENDERPATH_GL11:
5707         case RENDERPATH_GL13:
5708         case RENDERPATH_GL20:
5709         case RENDERPATH_SOFT:
5710         case RENDERPATH_GLES2:
5711                 break;
5712         case RENDERPATH_D3D9:
5713         case RENDERPATH_D3D10:
5714         case RENDERPATH_D3D11:
5715                 {
5716                         int i;
5717                         for (i = 0;i < 4;i++)
5718                         {
5719                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5720                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5721                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5722                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5723                         }
5724                 }
5725                 break;
5726         }
5727
5728         if (r_hdr.integer || r_bloom.integer)
5729         {
5730                 r_bloomstate.enabled = true;
5731                 r_bloomstate.hdr = r_hdr.integer != 0;
5732         }
5733
5734         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);
5735 }
5736
5737 void R_Bloom_CopyBloomTexture(float colorscale)
5738 {
5739         r_refdef.stats.bloom++;
5740
5741         // scale down screen texture to the bloom texture size
5742         CHECKGLERROR
5743         R_SetViewport(&r_bloomstate.viewport);
5744         GL_BlendFunc(GL_ONE, GL_ZERO);
5745         GL_Color(colorscale, colorscale, colorscale, 1);
5746         // 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...
5747         switch(vid.renderpath)
5748         {
5749         case RENDERPATH_GL11:
5750         case RENDERPATH_GL13:
5751         case RENDERPATH_GL20:
5752         case RENDERPATH_SOFT:
5753         case RENDERPATH_GLES2:
5754                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5755                 break;
5756         case RENDERPATH_D3D9:
5757         case RENDERPATH_D3D10:
5758         case RENDERPATH_D3D11:
5759                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5760                 break;
5761         }
5762         // TODO: do boxfilter scale-down in shader?
5763         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5764         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5765         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5766
5767         // we now have a bloom image in the framebuffer
5768         // copy it into the bloom image texture for later processing
5769         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);
5770         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5771 }
5772
5773 void R_Bloom_CopyHDRTexture(void)
5774 {
5775         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);
5776         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5777 }
5778
5779 void R_Bloom_MakeTexture(void)
5780 {
5781         int x, range, dir;
5782         float xoffset, yoffset, r, brighten;
5783
5784         r_refdef.stats.bloom++;
5785
5786         R_ResetViewRendering2D();
5787
5788         // we have a bloom image in the framebuffer
5789         CHECKGLERROR
5790         R_SetViewport(&r_bloomstate.viewport);
5791
5792         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5793         {
5794                 x *= 2;
5795                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5796                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5797                 GL_Color(r,r,r,1);
5798                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5799                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5800                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5801                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5802
5803                 // copy the vertically blurred bloom view to a texture
5804                 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);
5805                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5806         }
5807
5808         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5809         brighten = r_bloom_brighten.value;
5810         if (r_hdr.integer)
5811                 brighten *= r_hdr_range.value;
5812         brighten = sqrt(brighten);
5813         if(range >= 1)
5814                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5815         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5816
5817         for (dir = 0;dir < 2;dir++)
5818         {
5819                 // blend on at multiple vertical offsets to achieve a vertical blur
5820                 // TODO: do offset blends using GLSL
5821                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5822                 GL_BlendFunc(GL_ONE, GL_ZERO);
5823                 for (x = -range;x <= range;x++)
5824                 {
5825                         if (!dir){xoffset = 0;yoffset = x;}
5826                         else {xoffset = x;yoffset = 0;}
5827                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5828                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5829                         // compute a texcoord array with the specified x and y offset
5830                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5831                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5832                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5833                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5834                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5835                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5836                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5837                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5838                         // this r value looks like a 'dot' particle, fading sharply to
5839                         // black at the edges
5840                         // (probably not realistic but looks good enough)
5841                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5842                         //r = brighten/(range*2+1);
5843                         r = brighten / (range * 2 + 1);
5844                         if(range >= 1)
5845                                 r *= (1 - x*x/(float)(range*range));
5846                         GL_Color(r, r, r, 1);
5847                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5848                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5849                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5850                         GL_BlendFunc(GL_ONE, GL_ONE);
5851                 }
5852
5853                 // copy the vertically blurred bloom view to a texture
5854                 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);
5855                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5856         }
5857 }
5858
5859 void R_HDR_RenderBloomTexture(void)
5860 {
5861         int oldwidth, oldheight;
5862         float oldcolorscale;
5863         qboolean oldwaterstate;
5864
5865         oldwaterstate = r_waterstate.enabled;
5866         oldcolorscale = r_refdef.view.colorscale;
5867         oldwidth = r_refdef.view.width;
5868         oldheight = r_refdef.view.height;
5869         r_refdef.view.width = r_bloomstate.bloomwidth;
5870         r_refdef.view.height = r_bloomstate.bloomheight;
5871
5872         if(r_hdr.integer < 2)
5873                 r_waterstate.enabled = false;
5874
5875         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5876         // TODO: add exposure compensation features
5877         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5878
5879         r_refdef.view.showdebug = false;
5880         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5881
5882         R_ResetViewRendering3D();
5883
5884         R_ClearScreen(r_refdef.fogenabled);
5885         if (r_timereport_active)
5886                 R_TimeReport("HDRclear");
5887
5888         R_View_Update();
5889         if (r_timereport_active)
5890                 R_TimeReport("visibility");
5891
5892         // only do secondary renders with HDR if r_hdr is 2 or higher
5893         r_waterstate.numwaterplanes = 0;
5894         if (r_waterstate.enabled)
5895                 R_RenderWaterPlanes();
5896
5897         r_refdef.view.showdebug = true;
5898         R_RenderScene();
5899         r_waterstate.numwaterplanes = 0;
5900
5901         R_ResetViewRendering2D();
5902
5903         R_Bloom_CopyHDRTexture();
5904         R_Bloom_MakeTexture();
5905
5906         // restore the view settings
5907         r_waterstate.enabled = oldwaterstate;
5908         r_refdef.view.width = oldwidth;
5909         r_refdef.view.height = oldheight;
5910         r_refdef.view.colorscale = oldcolorscale;
5911
5912         R_ResetViewRendering3D();
5913
5914         R_ClearScreen(r_refdef.fogenabled);
5915         if (r_timereport_active)
5916                 R_TimeReport("viewclear");
5917 }
5918
5919 static void R_BlendView(void)
5920 {
5921         unsigned int permutation;
5922         float uservecs[4][4];
5923
5924         switch (vid.renderpath)
5925         {
5926         case RENDERPATH_GL20:
5927         case RENDERPATH_D3D9:
5928         case RENDERPATH_D3D10:
5929         case RENDERPATH_D3D11:
5930         case RENDERPATH_SOFT:
5931         case RENDERPATH_GLES2:
5932                 permutation =
5933                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5934                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5935                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5936                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5937                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5938
5939                 if (r_bloomstate.texture_screen)
5940                 {
5941                         // make sure the buffer is available
5942                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5943
5944                         R_ResetViewRendering2D();
5945
5946                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5947                         {
5948                                 // declare variables
5949                                 float speed;
5950                                 static float avgspeed;
5951
5952                                 speed = VectorLength(cl.movement_velocity);
5953
5954                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5955                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5956
5957                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5958                                 speed = bound(0, speed, 1);
5959                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5960
5961                                 // calculate values into a standard alpha
5962                                 cl.motionbluralpha = 1 - exp(-
5963                                                 (
5964                                                  (r_motionblur.value * speed / 80)
5965                                                  +
5966                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5967                                                 )
5968                                                 /
5969                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
5970                                            );
5971
5972                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5973                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5974                                 // apply the blur
5975                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
5976                                 {
5977                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5978                                         GL_Color(1, 1, 1, cl.motionbluralpha);
5979                                         switch(vid.renderpath)
5980                                         {
5981                                         case RENDERPATH_GL11:
5982                                         case RENDERPATH_GL13:
5983                                         case RENDERPATH_GL20:
5984                                         case RENDERPATH_SOFT:
5985                                         case RENDERPATH_GLES2:
5986                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5987                                                 break;
5988                                         case RENDERPATH_D3D9:
5989                                         case RENDERPATH_D3D10:
5990                                         case RENDERPATH_D3D11:
5991                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5992                                                 break;
5993                                         }
5994                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5995                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5996                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5997                                 }
5998                         }
5999
6000                         // copy view into the screen texture
6001                         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);
6002                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6003                 }
6004                 else if (!r_bloomstate.texture_bloom)
6005                 {
6006                         // we may still have to do view tint...
6007                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6008                         {
6009                                 // apply a color tint to the whole view
6010                                 R_ResetViewRendering2D();
6011                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6012                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6013                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6014                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6015                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6016                         }
6017                         break; // no screen processing, no bloom, skip it
6018                 }
6019
6020                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6021                 {
6022                         // render simple bloom effect
6023                         // copy the screen and shrink it and darken it for the bloom process
6024                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6025                         // make the bloom texture
6026                         R_Bloom_MakeTexture();
6027                 }
6028
6029 #if _MSC_VER >= 1400
6030 #define sscanf sscanf_s
6031 #endif
6032                 memset(uservecs, 0, sizeof(uservecs));
6033                 if (r_glsl_postprocess_uservec1_enable.integer)
6034                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6035                 if (r_glsl_postprocess_uservec2_enable.integer)
6036                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6037                 if (r_glsl_postprocess_uservec3_enable.integer)
6038                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6039                 if (r_glsl_postprocess_uservec4_enable.integer)
6040                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6041
6042                 R_ResetViewRendering2D();
6043                 GL_Color(1, 1, 1, 1);
6044                 GL_BlendFunc(GL_ONE, GL_ZERO);
6045
6046                 switch(vid.renderpath)
6047                 {
6048                 case RENDERPATH_GL20:
6049                 case RENDERPATH_GLES2:
6050                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6051                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6052                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6053                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6054                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6055                         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]);
6056                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6057                         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]);
6058                         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]);
6059                         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]);
6060                         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]);
6061                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6062                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6063                         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);
6064                         break;
6065                 case RENDERPATH_D3D9:
6066 #ifdef SUPPORTD3D
6067                         // 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...
6068                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6069                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6070                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6071                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6072                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6073                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6074                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6075                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6076                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6077                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6078                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6079                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6080                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6081                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6082 #endif
6083                         break;
6084                 case RENDERPATH_D3D10:
6085                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6086                         break;
6087                 case RENDERPATH_D3D11:
6088                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6089                         break;
6090                 case RENDERPATH_SOFT:
6091                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6092                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6093                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6094                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6095                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6096                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6097                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6098                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6099                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6100                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6101                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6102                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6103                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6104                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6105                         break;
6106                 default:
6107                         break;
6108                 }
6109                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6110                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6111                 break;
6112         case RENDERPATH_GL13:
6113         case RENDERPATH_GL11:
6114                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6115                 {
6116                         // apply a color tint to the whole view
6117                         R_ResetViewRendering2D();
6118                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6119                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6120                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6121                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6122                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6123                 }
6124                 break;
6125         }
6126 }
6127
6128 matrix4x4_t r_waterscrollmatrix;
6129
6130 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6131 {
6132         if (r_refdef.fog_density)
6133         {
6134                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6135                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6136                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6137
6138                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6139                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6140                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6141                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6142
6143                 {
6144                         vec3_t fogvec;
6145                         VectorCopy(r_refdef.fogcolor, fogvec);
6146                         //   color.rgb *= ContrastBoost * SceneBrightness;
6147                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6148                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6149                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6150                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6151                 }
6152         }
6153 }
6154
6155 void R_UpdateVariables(void)
6156 {
6157         R_Textures_Frame();
6158
6159         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6160
6161         r_refdef.farclip = r_farclip_base.value;
6162         if (r_refdef.scene.worldmodel)
6163                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6164         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6165
6166         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6167                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6168         r_refdef.polygonfactor = 0;
6169         r_refdef.polygonoffset = 0;
6170         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6171         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6172
6173         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6174         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6175         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6176         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6177         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6178         if (FAKELIGHT_ENABLED)
6179         {
6180                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6181         }
6182         if (r_showsurfaces.integer)
6183         {
6184                 r_refdef.scene.rtworld = false;
6185                 r_refdef.scene.rtworldshadows = false;
6186                 r_refdef.scene.rtdlight = false;
6187                 r_refdef.scene.rtdlightshadows = false;
6188                 r_refdef.lightmapintensity = 0;
6189         }
6190
6191         if (gamemode == GAME_NEHAHRA)
6192         {
6193                 if (gl_fogenable.integer)
6194                 {
6195                         r_refdef.oldgl_fogenable = true;
6196                         r_refdef.fog_density = gl_fogdensity.value;
6197                         r_refdef.fog_red = gl_fogred.value;
6198                         r_refdef.fog_green = gl_foggreen.value;
6199                         r_refdef.fog_blue = gl_fogblue.value;
6200                         r_refdef.fog_alpha = 1;
6201                         r_refdef.fog_start = 0;
6202                         r_refdef.fog_end = gl_skyclip.value;
6203                         r_refdef.fog_height = 1<<30;
6204                         r_refdef.fog_fadedepth = 128;
6205                 }
6206                 else if (r_refdef.oldgl_fogenable)
6207                 {
6208                         r_refdef.oldgl_fogenable = false;
6209                         r_refdef.fog_density = 0;
6210                         r_refdef.fog_red = 0;
6211                         r_refdef.fog_green = 0;
6212                         r_refdef.fog_blue = 0;
6213                         r_refdef.fog_alpha = 0;
6214                         r_refdef.fog_start = 0;
6215                         r_refdef.fog_end = 0;
6216                         r_refdef.fog_height = 1<<30;
6217                         r_refdef.fog_fadedepth = 128;
6218                 }
6219         }
6220
6221         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6222         r_refdef.fog_start = max(0, r_refdef.fog_start);
6223         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6224
6225         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6226
6227         if (r_refdef.fog_density && r_drawfog.integer)
6228         {
6229                 r_refdef.fogenabled = true;
6230                 // this is the point where the fog reaches 0.9986 alpha, which we
6231                 // consider a good enough cutoff point for the texture
6232                 // (0.9986 * 256 == 255.6)
6233                 if (r_fog_exp2.integer)
6234                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6235                 else
6236                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6237                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6238                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6239                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6240                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6241                         R_BuildFogHeightTexture();
6242                 // fog color was already set
6243                 // update the fog texture
6244                 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)
6245                         R_BuildFogTexture();
6246                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6247                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6248         }
6249         else
6250                 r_refdef.fogenabled = false;
6251
6252         switch(vid.renderpath)
6253         {
6254         case RENDERPATH_GL20:
6255         case RENDERPATH_D3D9:
6256         case RENDERPATH_D3D10:
6257         case RENDERPATH_D3D11:
6258         case RENDERPATH_SOFT:
6259         case RENDERPATH_GLES2:
6260                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6261                 {
6262                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6263                         {
6264                                 // build GLSL gamma texture
6265 #define RAMPWIDTH 256
6266                                 unsigned short ramp[RAMPWIDTH * 3];
6267                                 unsigned char rampbgr[RAMPWIDTH][4];
6268                                 int i;
6269
6270                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6271
6272                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6273                                 for(i = 0; i < RAMPWIDTH; ++i)
6274                                 {
6275                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6276                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6277                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6278                                         rampbgr[i][3] = 0;
6279                                 }
6280                                 if (r_texture_gammaramps)
6281                                 {
6282                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6283                                 }
6284                                 else
6285                                 {
6286                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6287                                 }
6288                         }
6289                 }
6290                 else
6291                 {
6292                         // remove GLSL gamma texture
6293                 }
6294                 break;
6295         case RENDERPATH_GL13:
6296         case RENDERPATH_GL11:
6297                 break;
6298         }
6299 }
6300
6301 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6302 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6303 /*
6304 ================
6305 R_SelectScene
6306 ================
6307 */
6308 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6309         if( scenetype != r_currentscenetype ) {
6310                 // store the old scenetype
6311                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6312                 r_currentscenetype = scenetype;
6313                 // move in the new scene
6314                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6315         }
6316 }
6317
6318 /*
6319 ================
6320 R_GetScenePointer
6321 ================
6322 */
6323 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6324 {
6325         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6326         if( scenetype == r_currentscenetype ) {
6327                 return &r_refdef.scene;
6328         } else {
6329                 return &r_scenes_store[ scenetype ];
6330         }
6331 }
6332
6333 /*
6334 ================
6335 R_RenderView
6336 ================
6337 */
6338 int dpsoftrast_test;
6339 void R_RenderView(void)
6340 {
6341         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6342
6343         dpsoftrast_test = r_test.integer;
6344
6345         if (r_timereport_active)
6346                 R_TimeReport("start");
6347         r_textureframe++; // used only by R_GetCurrentTexture
6348         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6349
6350         if(R_CompileShader_CheckStaticParms())
6351                 R_GLSL_Restart_f();
6352
6353         if (!r_drawentities.integer)
6354                 r_refdef.scene.numentities = 0;
6355
6356         R_AnimCache_ClearCache();
6357         R_FrameData_NewFrame();
6358
6359         /* adjust for stereo display */
6360         if(R_Stereo_Active())
6361         {
6362                 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);
6363                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6364         }
6365
6366         if (r_refdef.view.isoverlay)
6367         {
6368                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6369                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6370                 R_TimeReport("depthclear");
6371
6372                 r_refdef.view.showdebug = false;
6373
6374                 r_waterstate.enabled = false;
6375                 r_waterstate.numwaterplanes = 0;
6376
6377                 R_RenderScene();
6378
6379                 r_refdef.view.matrix = originalmatrix;
6380
6381                 CHECKGLERROR
6382                 return;
6383         }
6384
6385         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6386         {
6387                 r_refdef.view.matrix = originalmatrix;
6388                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6389         }
6390
6391         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6392
6393         R_RenderView_UpdateViewVectors();
6394
6395         R_Shadow_UpdateWorldLightSelection();
6396
6397         R_Bloom_StartFrame();
6398         R_Water_StartFrame();
6399
6400         CHECKGLERROR
6401         if (r_timereport_active)
6402                 R_TimeReport("viewsetup");
6403
6404         R_ResetViewRendering3D();
6405
6406         if (r_refdef.view.clear || r_refdef.fogenabled)
6407         {
6408                 R_ClearScreen(r_refdef.fogenabled);
6409                 if (r_timereport_active)
6410                         R_TimeReport("viewclear");
6411         }
6412         r_refdef.view.clear = true;
6413
6414         // this produces a bloom texture to be used in R_BlendView() later
6415         if (r_hdr.integer && r_bloomstate.bloomwidth)
6416         {
6417                 R_HDR_RenderBloomTexture();
6418                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6419                 r_textureframe++; // used only by R_GetCurrentTexture
6420         }
6421
6422         r_refdef.view.showdebug = true;
6423
6424         R_View_Update();
6425         if (r_timereport_active)
6426                 R_TimeReport("visibility");
6427
6428         r_waterstate.numwaterplanes = 0;
6429         if (r_waterstate.enabled)
6430                 R_RenderWaterPlanes();
6431
6432         R_RenderScene();
6433         r_waterstate.numwaterplanes = 0;
6434
6435         R_BlendView();
6436         if (r_timereport_active)
6437                 R_TimeReport("blendview");
6438
6439         GL_Scissor(0, 0, vid.width, vid.height);
6440         GL_ScissorTest(false);
6441
6442         r_refdef.view.matrix = originalmatrix;
6443
6444         CHECKGLERROR
6445 }
6446
6447 void R_RenderWaterPlanes(void)
6448 {
6449         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6450         {
6451                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6452                 if (r_timereport_active)
6453                         R_TimeReport("waterworld");
6454         }
6455
6456         // don't let sound skip if going slow
6457         if (r_refdef.scene.extraupdate)
6458                 S_ExtraUpdate ();
6459
6460         R_DrawModelsAddWaterPlanes();
6461         if (r_timereport_active)
6462                 R_TimeReport("watermodels");
6463
6464         if (r_waterstate.numwaterplanes)
6465         {
6466                 R_Water_ProcessPlanes();
6467                 if (r_timereport_active)
6468                         R_TimeReport("waterscenes");
6469         }
6470 }
6471
6472 extern void R_DrawLightningBeams (void);
6473 extern void VM_CL_AddPolygonsToMeshQueue (void);
6474 extern void R_DrawPortals (void);
6475 extern cvar_t cl_locs_show;
6476 static void R_DrawLocs(void);
6477 static void R_DrawEntityBBoxes(void);
6478 static void R_DrawModelDecals(void);
6479 extern void R_DrawModelShadows(void);
6480 extern void R_DrawModelShadowMaps(void);
6481 extern cvar_t cl_decals_newsystem;
6482 extern qboolean r_shadow_usingdeferredprepass;
6483 void R_RenderScene(void)
6484 {
6485         qboolean shadowmapping = false;
6486
6487         if (r_timereport_active)
6488                 R_TimeReport("beginscene");
6489
6490         r_refdef.stats.renders++;
6491
6492         R_UpdateFogColor();
6493
6494         // don't let sound skip if going slow
6495         if (r_refdef.scene.extraupdate)
6496                 S_ExtraUpdate ();
6497
6498         R_MeshQueue_BeginScene();
6499
6500         R_SkyStartFrame();
6501
6502         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);
6503
6504         if (r_timereport_active)
6505                 R_TimeReport("skystartframe");
6506
6507         if (cl.csqc_vidvars.drawworld)
6508         {
6509                 // don't let sound skip if going slow
6510                 if (r_refdef.scene.extraupdate)
6511                         S_ExtraUpdate ();
6512
6513                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6514                 {
6515                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6516                         if (r_timereport_active)
6517                                 R_TimeReport("worldsky");
6518                 }
6519
6520                 if (R_DrawBrushModelsSky() && r_timereport_active)
6521                         R_TimeReport("bmodelsky");
6522
6523                 if (skyrendermasked && skyrenderlater)
6524                 {
6525                         // we have to force off the water clipping plane while rendering sky
6526                         R_SetupView(false);
6527                         R_Sky();
6528                         R_SetupView(true);
6529                         if (r_timereport_active)
6530                                 R_TimeReport("sky");
6531                 }
6532         }
6533
6534         R_AnimCache_CacheVisibleEntities();
6535         if (r_timereport_active)
6536                 R_TimeReport("animation");
6537
6538         R_Shadow_PrepareLights();
6539         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6540                 R_Shadow_PrepareModelShadows();
6541         if (r_timereport_active)
6542                 R_TimeReport("preparelights");
6543
6544         if (R_Shadow_ShadowMappingEnabled())
6545                 shadowmapping = true;
6546
6547         if (r_shadow_usingdeferredprepass)
6548                 R_Shadow_DrawPrepass();
6549
6550         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6551         {
6552                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6553                 if (r_timereport_active)
6554                         R_TimeReport("worlddepth");
6555         }
6556         if (r_depthfirst.integer >= 2)
6557         {
6558                 R_DrawModelsDepth();
6559                 if (r_timereport_active)
6560                         R_TimeReport("modeldepth");
6561         }
6562
6563         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6564         {
6565                 R_DrawModelShadowMaps();
6566                 R_ResetViewRendering3D();
6567                 // don't let sound skip if going slow
6568                 if (r_refdef.scene.extraupdate)
6569                         S_ExtraUpdate ();
6570         }
6571
6572         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6573         {
6574                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6575                 if (r_timereport_active)
6576                         R_TimeReport("world");
6577         }
6578
6579         // don't let sound skip if going slow
6580         if (r_refdef.scene.extraupdate)
6581                 S_ExtraUpdate ();
6582
6583         R_DrawModels();
6584         if (r_timereport_active)
6585                 R_TimeReport("models");
6586
6587         // don't let sound skip if going slow
6588         if (r_refdef.scene.extraupdate)
6589                 S_ExtraUpdate ();
6590
6591         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6592         {
6593                 R_DrawModelShadows();
6594                 R_ResetViewRendering3D();
6595                 // don't let sound skip if going slow
6596                 if (r_refdef.scene.extraupdate)
6597                         S_ExtraUpdate ();
6598         }
6599
6600         if (!r_shadow_usingdeferredprepass)
6601         {
6602                 R_Shadow_DrawLights();
6603                 if (r_timereport_active)
6604                         R_TimeReport("rtlights");
6605         }
6606
6607         // don't let sound skip if going slow
6608         if (r_refdef.scene.extraupdate)
6609                 S_ExtraUpdate ();
6610
6611         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6612         {
6613                 R_DrawModelShadows();
6614                 R_ResetViewRendering3D();
6615                 // don't let sound skip if going slow
6616                 if (r_refdef.scene.extraupdate)
6617                         S_ExtraUpdate ();
6618         }
6619
6620         if (cl.csqc_vidvars.drawworld)
6621         {
6622                 if (cl_decals_newsystem.integer)
6623                 {
6624                         R_DrawModelDecals();
6625                         if (r_timereport_active)
6626                                 R_TimeReport("modeldecals");
6627                 }
6628                 else
6629                 {
6630                         R_DrawDecals();
6631                         if (r_timereport_active)
6632                                 R_TimeReport("decals");
6633                 }
6634
6635                 R_DrawParticles();
6636                 if (r_timereport_active)
6637                         R_TimeReport("particles");
6638
6639                 R_DrawExplosions();
6640                 if (r_timereport_active)
6641                         R_TimeReport("explosions");
6642
6643                 R_DrawLightningBeams();
6644                 if (r_timereport_active)
6645                         R_TimeReport("lightning");
6646         }
6647
6648         VM_CL_AddPolygonsToMeshQueue();
6649
6650         if (r_refdef.view.showdebug)
6651         {
6652                 if (cl_locs_show.integer)
6653                 {
6654                         R_DrawLocs();
6655                         if (r_timereport_active)
6656                                 R_TimeReport("showlocs");
6657                 }
6658
6659                 if (r_drawportals.integer)
6660                 {
6661                         R_DrawPortals();
6662                         if (r_timereport_active)
6663                                 R_TimeReport("portals");
6664                 }
6665
6666                 if (r_showbboxes.value > 0)
6667                 {
6668                         R_DrawEntityBBoxes();
6669                         if (r_timereport_active)
6670                                 R_TimeReport("bboxes");
6671                 }
6672         }
6673
6674         R_MeshQueue_RenderTransparent();
6675         if (r_timereport_active)
6676                 R_TimeReport("drawtrans");
6677
6678         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))
6679         {
6680                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6681                 if (r_timereport_active)
6682                         R_TimeReport("worlddebug");
6683                 R_DrawModelsDebug();
6684                 if (r_timereport_active)
6685                         R_TimeReport("modeldebug");
6686         }
6687
6688         if (cl.csqc_vidvars.drawworld)
6689         {
6690                 R_Shadow_DrawCoronas();
6691                 if (r_timereport_active)
6692                         R_TimeReport("coronas");
6693         }
6694
6695 #if 0
6696         {
6697                 GL_DepthTest(false);
6698                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6699                 GL_Color(1, 1, 1, 1);
6700                 qglBegin(GL_POLYGON);
6701                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6702                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6703                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6704                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6705                 qglEnd();
6706                 qglBegin(GL_POLYGON);
6707                 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]);
6708                 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]);
6709                 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]);
6710                 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]);
6711                 qglEnd();
6712                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6713         }
6714 #endif
6715
6716         // don't let sound skip if going slow
6717         if (r_refdef.scene.extraupdate)
6718                 S_ExtraUpdate ();
6719
6720         R_ResetViewRendering2D();
6721 }
6722
6723 static const unsigned short bboxelements[36] =
6724 {
6725         5, 1, 3, 5, 3, 7,
6726         6, 2, 0, 6, 0, 4,
6727         7, 3, 2, 7, 2, 6,
6728         4, 0, 1, 4, 1, 5,
6729         4, 5, 7, 4, 7, 6,
6730         1, 0, 2, 1, 2, 3,
6731 };
6732
6733 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6734 {
6735         int i;
6736         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6737
6738         RSurf_ActiveWorldEntity();
6739
6740         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6741         GL_DepthMask(false);
6742         GL_DepthRange(0, 1);
6743         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6744 //      R_Mesh_ResetTextureState();
6745
6746         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6747         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6748         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6749         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6750         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6751         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6752         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6753         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6754         R_FillColors(color4f, 8, cr, cg, cb, ca);
6755         if (r_refdef.fogenabled)
6756         {
6757                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6758                 {
6759                         f1 = RSurf_FogVertex(v);
6760                         f2 = 1 - f1;
6761                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6762                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6763                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6764                 }
6765         }
6766         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6767         R_Mesh_ResetTextureState();
6768         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6769         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6770 }
6771
6772 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6773 {
6774         int i;
6775         float color[4];
6776         prvm_edict_t *edict;
6777         prvm_prog_t *prog_save = prog;
6778
6779         // this function draws bounding boxes of server entities
6780         if (!sv.active)
6781                 return;
6782
6783         GL_CullFace(GL_NONE);
6784         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6785
6786         prog = 0;
6787         SV_VM_Begin();
6788         for (i = 0;i < numsurfaces;i++)
6789         {
6790                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6791                 switch ((int)edict->fields.server->solid)
6792                 {
6793                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6794                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6795                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6796                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6797                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6798                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6799                 }
6800                 color[3] *= r_showbboxes.value;
6801                 color[3] = bound(0, color[3], 1);
6802                 GL_DepthTest(!r_showdisabledepthtest.integer);
6803                 GL_CullFace(r_refdef.view.cullface_front);
6804                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6805         }
6806         SV_VM_End();
6807         prog = prog_save;
6808 }
6809
6810 static void R_DrawEntityBBoxes(void)
6811 {
6812         int i;
6813         prvm_edict_t *edict;
6814         vec3_t center;
6815         prvm_prog_t *prog_save = prog;
6816
6817         // this function draws bounding boxes of server entities
6818         if (!sv.active)
6819                 return;
6820
6821         prog = 0;
6822         SV_VM_Begin();
6823         for (i = 0;i < prog->num_edicts;i++)
6824         {
6825                 edict = PRVM_EDICT_NUM(i);
6826                 if (edict->priv.server->free)
6827                         continue;
6828                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6829                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6830                         continue;
6831                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6832                         continue;
6833                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6834                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6835         }
6836         SV_VM_End();
6837         prog = prog_save;
6838 }
6839
6840 static const int nomodelelement3i[24] =
6841 {
6842         5, 2, 0,
6843         5, 1, 2,
6844         5, 0, 3,
6845         5, 3, 1,
6846         0, 2, 4,
6847         2, 1, 4,
6848         3, 0, 4,
6849         1, 3, 4
6850 };
6851
6852 static const unsigned short nomodelelement3s[24] =
6853 {
6854         5, 2, 0,
6855         5, 1, 2,
6856         5, 0, 3,
6857         5, 3, 1,
6858         0, 2, 4,
6859         2, 1, 4,
6860         3, 0, 4,
6861         1, 3, 4
6862 };
6863
6864 static const float nomodelvertex3f[6*3] =
6865 {
6866         -16,   0,   0,
6867          16,   0,   0,
6868           0, -16,   0,
6869           0,  16,   0,
6870           0,   0, -16,
6871           0,   0,  16
6872 };
6873
6874 static const float nomodelcolor4f[6*4] =
6875 {
6876         0.0f, 0.0f, 0.5f, 1.0f,
6877         0.0f, 0.0f, 0.5f, 1.0f,
6878         0.0f, 0.5f, 0.0f, 1.0f,
6879         0.0f, 0.5f, 0.0f, 1.0f,
6880         0.5f, 0.0f, 0.0f, 1.0f,
6881         0.5f, 0.0f, 0.0f, 1.0f
6882 };
6883
6884 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6885 {
6886         int i;
6887         float f1, f2, *c;
6888         float color4f[6*4];
6889
6890         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);
6891
6892         // this is only called once per entity so numsurfaces is always 1, and
6893         // surfacelist is always {0}, so this code does not handle batches
6894
6895         if (rsurface.ent_flags & RENDER_ADDITIVE)
6896         {
6897                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6898                 GL_DepthMask(false);
6899         }
6900         else if (rsurface.colormod[3] < 1)
6901         {
6902                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6903                 GL_DepthMask(false);
6904         }
6905         else
6906         {
6907                 GL_BlendFunc(GL_ONE, GL_ZERO);
6908                 GL_DepthMask(true);
6909         }
6910         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6911         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6912         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6913         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6914         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6915         for (i = 0, c = color4f;i < 6;i++, c += 4)
6916         {
6917                 c[0] *= rsurface.colormod[0];
6918                 c[1] *= rsurface.colormod[1];
6919                 c[2] *= rsurface.colormod[2];
6920                 c[3] *= rsurface.colormod[3];
6921         }
6922         if (r_refdef.fogenabled)
6923         {
6924                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6925                 {
6926                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6927                         f2 = 1 - f1;
6928                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6929                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6930                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6931                 }
6932         }
6933 //      R_Mesh_ResetTextureState();
6934         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6935         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6936         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6937 }
6938
6939 void R_DrawNoModel(entity_render_t *ent)
6940 {
6941         vec3_t org;
6942         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6943         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6944                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6945         else
6946                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6947 }
6948
6949 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6950 {
6951         vec3_t right1, right2, diff, normal;
6952
6953         VectorSubtract (org2, org1, normal);
6954
6955         // calculate 'right' vector for start
6956         VectorSubtract (r_refdef.view.origin, org1, diff);
6957         CrossProduct (normal, diff, right1);
6958         VectorNormalize (right1);
6959
6960         // calculate 'right' vector for end
6961         VectorSubtract (r_refdef.view.origin, org2, diff);
6962         CrossProduct (normal, diff, right2);
6963         VectorNormalize (right2);
6964
6965         vert[ 0] = org1[0] + width * right1[0];
6966         vert[ 1] = org1[1] + width * right1[1];
6967         vert[ 2] = org1[2] + width * right1[2];
6968         vert[ 3] = org1[0] - width * right1[0];
6969         vert[ 4] = org1[1] - width * right1[1];
6970         vert[ 5] = org1[2] - width * right1[2];
6971         vert[ 6] = org2[0] - width * right2[0];
6972         vert[ 7] = org2[1] - width * right2[1];
6973         vert[ 8] = org2[2] - width * right2[2];
6974         vert[ 9] = org2[0] + width * right2[0];
6975         vert[10] = org2[1] + width * right2[1];
6976         vert[11] = org2[2] + width * right2[2];
6977 }
6978
6979 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)
6980 {
6981         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6982         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6983         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6984         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6985         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
6986         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
6987         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
6988         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
6989         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
6990         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
6991         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
6992         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
6993 }
6994
6995 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
6996 {
6997         int i;
6998         float *vertex3f;
6999         float v[3];
7000         VectorSet(v, x, y, z);
7001         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7002                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7003                         break;
7004         if (i == mesh->numvertices)
7005         {
7006                 if (mesh->numvertices < mesh->maxvertices)
7007                 {
7008                         VectorCopy(v, vertex3f);
7009                         mesh->numvertices++;
7010                 }
7011                 return mesh->numvertices;
7012         }
7013         else
7014                 return i;
7015 }
7016
7017 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7018 {
7019         int i;
7020         int *e, element[3];
7021         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7022         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7023         e = mesh->element3i + mesh->numtriangles * 3;
7024         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7025         {
7026                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7027                 if (mesh->numtriangles < mesh->maxtriangles)
7028                 {
7029                         *e++ = element[0];
7030                         *e++ = element[1];
7031                         *e++ = element[2];
7032                         mesh->numtriangles++;
7033                 }
7034                 element[1] = element[2];
7035         }
7036 }
7037
7038 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7039 {
7040         int i;
7041         int *e, element[3];
7042         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7043         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7044         e = mesh->element3i + mesh->numtriangles * 3;
7045         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7046         {
7047                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7048                 if (mesh->numtriangles < mesh->maxtriangles)
7049                 {
7050                         *e++ = element[0];
7051                         *e++ = element[1];
7052                         *e++ = element[2];
7053                         mesh->numtriangles++;
7054                 }
7055                 element[1] = element[2];
7056         }
7057 }
7058
7059 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7060 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7061 {
7062         int planenum, planenum2;
7063         int w;
7064         int tempnumpoints;
7065         mplane_t *plane, *plane2;
7066         double maxdist;
7067         double temppoints[2][256*3];
7068         // figure out how large a bounding box we need to properly compute this brush
7069         maxdist = 0;
7070         for (w = 0;w < numplanes;w++)
7071                 maxdist = max(maxdist, fabs(planes[w].dist));
7072         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7073         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7074         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7075         {
7076                 w = 0;
7077                 tempnumpoints = 4;
7078                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7079                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7080                 {
7081                         if (planenum2 == planenum)
7082                                 continue;
7083                         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);
7084                         w = !w;
7085                 }
7086                 if (tempnumpoints < 3)
7087                         continue;
7088                 // generate elements forming a triangle fan for this polygon
7089                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7090         }
7091 }
7092
7093 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)
7094 {
7095         texturelayer_t *layer;
7096         layer = t->currentlayers + t->currentnumlayers++;
7097         layer->type = type;
7098         layer->depthmask = depthmask;
7099         layer->blendfunc1 = blendfunc1;
7100         layer->blendfunc2 = blendfunc2;
7101         layer->texture = texture;
7102         layer->texmatrix = *matrix;
7103         layer->color[0] = r;
7104         layer->color[1] = g;
7105         layer->color[2] = b;
7106         layer->color[3] = a;
7107 }
7108
7109 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7110 {
7111         if(parms[0] == 0 && parms[1] == 0)
7112                 return false;
7113         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7114                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7115                         return false;
7116         return true;
7117 }
7118
7119 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7120 {
7121         double index, f;
7122         index = parms[2] + r_refdef.scene.time * parms[3];
7123         index -= floor(index);
7124         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7125         {
7126         default:
7127         case Q3WAVEFUNC_NONE:
7128         case Q3WAVEFUNC_NOISE:
7129         case Q3WAVEFUNC_COUNT:
7130                 f = 0;
7131                 break;
7132         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7133         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7134         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7135         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7136         case Q3WAVEFUNC_TRIANGLE:
7137                 index *= 4;
7138                 f = index - floor(index);
7139                 if (index < 1)
7140                         f = f;
7141                 else if (index < 2)
7142                         f = 1 - f;
7143                 else if (index < 3)
7144                         f = -f;
7145                 else
7146                         f = -(1 - f);
7147                 break;
7148         }
7149         f = parms[0] + parms[1] * f;
7150         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7151                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7152         return (float) f;
7153 }
7154
7155 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7156 {
7157         int w, h, idx;
7158         float f;
7159         float tcmat[12];
7160         matrix4x4_t matrix, temp;
7161         switch(tcmod->tcmod)
7162         {
7163                 case Q3TCMOD_COUNT:
7164                 case Q3TCMOD_NONE:
7165                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7166                                 matrix = r_waterscrollmatrix;
7167                         else
7168                                 matrix = identitymatrix;
7169                         break;
7170                 case Q3TCMOD_ENTITYTRANSLATE:
7171                         // this is used in Q3 to allow the gamecode to control texcoord
7172                         // scrolling on the entity, which is not supported in darkplaces yet.
7173                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7174                         break;
7175                 case Q3TCMOD_ROTATE:
7176                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7177                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7178                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7179                         break;
7180                 case Q3TCMOD_SCALE:
7181                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7182                         break;
7183                 case Q3TCMOD_SCROLL:
7184                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7185                         break;
7186                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7187                         w = (int) tcmod->parms[0];
7188                         h = (int) tcmod->parms[1];
7189                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7190                         f = f - floor(f);
7191                         idx = (int) floor(f * w * h);
7192                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7193                         break;
7194                 case Q3TCMOD_STRETCH:
7195                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7196                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7197                         break;
7198                 case Q3TCMOD_TRANSFORM:
7199                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7200                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7201                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7202                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7203                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7204                         break;
7205                 case Q3TCMOD_TURBULENT:
7206                         // this is handled in the RSurf_PrepareVertices function
7207                         matrix = identitymatrix;
7208                         break;
7209         }
7210         temp = *texmatrix;
7211         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7212 }
7213
7214 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7215 {
7216         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7217         char name[MAX_QPATH];
7218         skinframe_t *skinframe;
7219         unsigned char pixels[296*194];
7220         strlcpy(cache->name, skinname, sizeof(cache->name));
7221         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7222         if (developer_loading.integer)
7223                 Con_Printf("loading %s\n", name);
7224         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7225         if (!skinframe || !skinframe->base)
7226         {
7227                 unsigned char *f;
7228                 fs_offset_t filesize;
7229                 skinframe = NULL;
7230                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7231                 if (f)
7232                 {
7233                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7234                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7235                         Mem_Free(f);
7236                 }
7237         }
7238         cache->skinframe = skinframe;
7239 }
7240
7241 texture_t *R_GetCurrentTexture(texture_t *t)
7242 {
7243         int i;
7244         const entity_render_t *ent = rsurface.entity;
7245         dp_model_t *model = ent->model;
7246         q3shaderinfo_layer_tcmod_t *tcmod;
7247
7248         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7249                 return t->currentframe;
7250         t->update_lastrenderframe = r_textureframe;
7251         t->update_lastrenderentity = (void *)ent;
7252
7253         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7254                 t->camera_entity = ent->entitynumber;
7255         else
7256                 t->camera_entity = 0;
7257
7258         // switch to an alternate material if this is a q1bsp animated material
7259         {
7260                 texture_t *texture = t;
7261                 int s = rsurface.ent_skinnum;
7262                 if ((unsigned int)s >= (unsigned int)model->numskins)
7263                         s = 0;
7264                 if (model->skinscenes)
7265                 {
7266                         if (model->skinscenes[s].framecount > 1)
7267                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7268                         else
7269                                 s = model->skinscenes[s].firstframe;
7270                 }
7271                 if (s > 0)
7272                         t = t + s * model->num_surfaces;
7273                 if (t->animated)
7274                 {
7275                         // use an alternate animation if the entity's frame is not 0,
7276                         // and only if the texture has an alternate animation
7277                         if (rsurface.ent_alttextures && t->anim_total[1])
7278                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7279                         else
7280                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7281                 }
7282                 texture->currentframe = t;
7283         }
7284
7285         // update currentskinframe to be a qw skin or animation frame
7286         if (rsurface.ent_qwskin >= 0)
7287         {
7288                 i = rsurface.ent_qwskin;
7289                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7290                 {
7291                         r_qwskincache_size = cl.maxclients;
7292                         if (r_qwskincache)
7293                                 Mem_Free(r_qwskincache);
7294                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7295                 }
7296                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7297                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7298                 t->currentskinframe = r_qwskincache[i].skinframe;
7299                 if (t->currentskinframe == NULL)
7300                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7301         }
7302         else if (t->numskinframes >= 2)
7303                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7304         if (t->backgroundnumskinframes >= 2)
7305                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7306
7307         t->currentmaterialflags = t->basematerialflags;
7308         t->currentalpha = rsurface.colormod[3];
7309         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7310                 t->currentalpha *= r_wateralpha.value;
7311         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7312                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7313         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7314                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7315         if (!(rsurface.ent_flags & RENDER_LIGHT))
7316                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7317         else if (FAKELIGHT_ENABLED)
7318         {
7319                         // no modellight if using fakelight for the map
7320         }
7321         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7322         {
7323                 // pick a model lighting mode
7324                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7325                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7326                 else
7327                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7328         }
7329         if (rsurface.ent_flags & RENDER_ADDITIVE)
7330                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7331         else if (t->currentalpha < 1)
7332                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7333         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7334                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7335         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7336                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7337         if (t->backgroundnumskinframes)
7338                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7339         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7340         {
7341                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7342                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7343         }
7344         else
7345                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7346         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7347                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7348
7349         // there is no tcmod
7350         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7351         {
7352                 t->currenttexmatrix = r_waterscrollmatrix;
7353                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7354         }
7355         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7356         {
7357                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7358                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7359         }
7360
7361         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7362                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7363         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7364                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7365
7366         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7367         if (t->currentskinframe->qpixels)
7368                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7369         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7370         if (!t->basetexture)
7371                 t->basetexture = r_texture_notexture;
7372         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7373         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7374         t->nmaptexture = t->currentskinframe->nmap;
7375         if (!t->nmaptexture)
7376                 t->nmaptexture = r_texture_blanknormalmap;
7377         t->glosstexture = r_texture_black;
7378         t->glowtexture = t->currentskinframe->glow;
7379         t->fogtexture = t->currentskinframe->fog;
7380         t->reflectmasktexture = t->currentskinframe->reflect;
7381         if (t->backgroundnumskinframes)
7382         {
7383                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7384                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7385                 t->backgroundglosstexture = r_texture_black;
7386                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7387                 if (!t->backgroundnmaptexture)
7388                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7389         }
7390         else
7391         {
7392                 t->backgroundbasetexture = r_texture_white;
7393                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7394                 t->backgroundglosstexture = r_texture_black;
7395                 t->backgroundglowtexture = NULL;
7396         }
7397         t->specularpower = r_shadow_glossexponent.value;
7398         // TODO: store reference values for these in the texture?
7399         t->specularscale = 0;
7400         if (r_shadow_gloss.integer > 0)
7401         {
7402                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7403                 {
7404                         if (r_shadow_glossintensity.value > 0)
7405                         {
7406                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7407                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7408                                 t->specularscale = r_shadow_glossintensity.value;
7409                         }
7410                 }
7411                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7412                 {
7413                         t->glosstexture = r_texture_white;
7414                         t->backgroundglosstexture = r_texture_white;
7415                         t->specularscale = r_shadow_gloss2intensity.value;
7416                         t->specularpower = r_shadow_gloss2exponent.value;
7417                 }
7418         }
7419         t->specularscale *= t->specularscalemod;
7420         t->specularpower *= t->specularpowermod;
7421
7422         // lightmaps mode looks bad with dlights using actual texturing, so turn
7423         // off the colormap and glossmap, but leave the normalmap on as it still
7424         // accurately represents the shading involved
7425         if (gl_lightmaps.integer)
7426         {
7427                 t->basetexture = r_texture_grey128;
7428                 t->pantstexture = r_texture_black;
7429                 t->shirttexture = r_texture_black;
7430                 t->nmaptexture = r_texture_blanknormalmap;
7431                 t->glosstexture = r_texture_black;
7432                 t->glowtexture = NULL;
7433                 t->fogtexture = NULL;
7434                 t->reflectmasktexture = NULL;
7435                 t->backgroundbasetexture = NULL;
7436                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7437                 t->backgroundglosstexture = r_texture_black;
7438                 t->backgroundglowtexture = NULL;
7439                 t->specularscale = 0;
7440                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7441         }
7442
7443         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7444         VectorClear(t->dlightcolor);
7445         t->currentnumlayers = 0;
7446         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7447         {
7448                 int blendfunc1, blendfunc2;
7449                 qboolean depthmask;
7450                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7451                 {
7452                         blendfunc1 = GL_SRC_ALPHA;
7453                         blendfunc2 = GL_ONE;
7454                 }
7455                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7456                 {
7457                         blendfunc1 = GL_SRC_ALPHA;
7458                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7459                 }
7460                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7461                 {
7462                         blendfunc1 = t->customblendfunc[0];
7463                         blendfunc2 = t->customblendfunc[1];
7464                 }
7465                 else
7466                 {
7467                         blendfunc1 = GL_ONE;
7468                         blendfunc2 = GL_ZERO;
7469                 }
7470                 // don't colormod evilblend textures
7471                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7472                         VectorSet(t->lightmapcolor, 1, 1, 1);
7473                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7474                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7475                 {
7476                         // fullbright is not affected by r_refdef.lightmapintensity
7477                         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]);
7478                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7479                                 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]);
7480                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7481                                 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]);
7482                 }
7483                 else
7484                 {
7485                         vec3_t ambientcolor;
7486                         float colorscale;
7487                         // set the color tint used for lights affecting this surface
7488                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7489                         colorscale = 2;
7490                         // q3bsp has no lightmap updates, so the lightstylevalue that
7491                         // would normally be baked into the lightmap must be
7492                         // applied to the color
7493                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7494                         if (model->type == mod_brushq3)
7495                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7496                         colorscale *= r_refdef.lightmapintensity;
7497                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7498                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7499                         // basic lit geometry
7500                         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]);
7501                         // add pants/shirt if needed
7502                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7503                                 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]);
7504                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7505                                 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]);
7506                         // now add ambient passes if needed
7507                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7508                         {
7509                                 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]);
7510                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7511                                         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]);
7512                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7513                                         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]);
7514                         }
7515                 }
7516                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7517                         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]);
7518                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7519                 {
7520                         // if this is opaque use alpha blend which will darken the earlier
7521                         // passes cheaply.
7522                         //
7523                         // if this is an alpha blended material, all the earlier passes
7524                         // were darkened by fog already, so we only need to add the fog
7525                         // color ontop through the fog mask texture
7526                         //
7527                         // if this is an additive blended material, all the earlier passes
7528                         // were darkened by fog already, and we should not add fog color
7529                         // (because the background was not darkened, there is no fog color
7530                         // that was lost behind it).
7531                         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]);
7532                 }
7533         }
7534
7535         return t->currentframe;
7536 }
7537
7538 rsurfacestate_t rsurface;
7539
7540 void RSurf_ActiveWorldEntity(void)
7541 {
7542         dp_model_t *model = r_refdef.scene.worldmodel;
7543         //if (rsurface.entity == r_refdef.scene.worldentity)
7544         //      return;
7545         rsurface.entity = r_refdef.scene.worldentity;
7546         rsurface.skeleton = NULL;
7547         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7548         rsurface.ent_skinnum = 0;
7549         rsurface.ent_qwskin = -1;
7550         rsurface.ent_shadertime = 0;
7551         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7552         rsurface.matrix = identitymatrix;
7553         rsurface.inversematrix = identitymatrix;
7554         rsurface.matrixscale = 1;
7555         rsurface.inversematrixscale = 1;
7556         R_EntityMatrix(&identitymatrix);
7557         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7558         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7559         rsurface.fograngerecip = r_refdef.fograngerecip;
7560         rsurface.fogheightfade = r_refdef.fogheightfade;
7561         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7562         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7563         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7564         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7565         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7566         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7567         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7568         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7569         rsurface.colormod[3] = 1;
7570         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);
7571         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7572         rsurface.frameblend[0].lerp = 1;
7573         rsurface.ent_alttextures = false;
7574         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7575         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7576         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7577         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7578         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7579         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7580         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7581         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7582         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7583         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7584         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7585         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7586         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7587         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7588         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7589         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7590         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7591         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7592         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7593         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7594         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7595         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7596         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7597         rsurface.modelelement3i = model->surfmesh.data_element3i;
7598         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7599         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7600         rsurface.modelelement3s = model->surfmesh.data_element3s;
7601         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7602         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7603         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7604         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7605         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7606         rsurface.modelsurfaces = model->data_surfaces;
7607         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7608         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7609         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7610         rsurface.modelgeneratedvertex = false;
7611         rsurface.batchgeneratedvertex = false;
7612         rsurface.batchfirstvertex = 0;
7613         rsurface.batchnumvertices = 0;
7614         rsurface.batchfirsttriangle = 0;
7615         rsurface.batchnumtriangles = 0;
7616         rsurface.batchvertex3f  = NULL;
7617         rsurface.batchvertex3f_vertexbuffer = NULL;
7618         rsurface.batchvertex3f_bufferoffset = 0;
7619         rsurface.batchsvector3f = NULL;
7620         rsurface.batchsvector3f_vertexbuffer = NULL;
7621         rsurface.batchsvector3f_bufferoffset = 0;
7622         rsurface.batchtvector3f = NULL;
7623         rsurface.batchtvector3f_vertexbuffer = NULL;
7624         rsurface.batchtvector3f_bufferoffset = 0;
7625         rsurface.batchnormal3f  = NULL;
7626         rsurface.batchnormal3f_vertexbuffer = NULL;
7627         rsurface.batchnormal3f_bufferoffset = 0;
7628         rsurface.batchlightmapcolor4f = NULL;
7629         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7630         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7631         rsurface.batchtexcoordtexture2f = NULL;
7632         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7633         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7634         rsurface.batchtexcoordlightmap2f = NULL;
7635         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7636         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7637         rsurface.batchvertexmesh = NULL;
7638         rsurface.batchvertexmeshbuffer = NULL;
7639         rsurface.batchvertex3fbuffer = NULL;
7640         rsurface.batchelement3i = NULL;
7641         rsurface.batchelement3i_indexbuffer = NULL;
7642         rsurface.batchelement3i_bufferoffset = 0;
7643         rsurface.batchelement3s = NULL;
7644         rsurface.batchelement3s_indexbuffer = NULL;
7645         rsurface.batchelement3s_bufferoffset = 0;
7646         rsurface.passcolor4f = NULL;
7647         rsurface.passcolor4f_vertexbuffer = NULL;
7648         rsurface.passcolor4f_bufferoffset = 0;
7649 }
7650
7651 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7652 {
7653         dp_model_t *model = ent->model;
7654         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7655         //      return;
7656         rsurface.entity = (entity_render_t *)ent;
7657         rsurface.skeleton = ent->skeleton;
7658         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7659         rsurface.ent_skinnum = ent->skinnum;
7660         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;
7661         rsurface.ent_shadertime = ent->shadertime;
7662         rsurface.ent_flags = ent->flags;
7663         rsurface.matrix = ent->matrix;
7664         rsurface.inversematrix = ent->inversematrix;
7665         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7666         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7667         R_EntityMatrix(&rsurface.matrix);
7668         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7669         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7670         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7671         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7672         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7673         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7674         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7675         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7676         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7677         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7678         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7679         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7680         rsurface.colormod[3] = ent->alpha;
7681         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7682         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7683         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7684         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7685         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7686         if (ent->model->brush.submodel && !prepass)
7687         {
7688                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7689                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7690         }
7691         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7692         {
7693                 if (ent->animcache_vertex3f)
7694                 {
7695                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7696                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7697                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7698                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7699                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7700                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7701                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7702                 }
7703                 else if (wanttangents)
7704                 {
7705                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7706                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7707                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7708                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7709                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7710                         rsurface.modelvertexmesh = NULL;
7711                         rsurface.modelvertexmeshbuffer = NULL;
7712                         rsurface.modelvertex3fbuffer = NULL;
7713                 }
7714                 else if (wantnormals)
7715                 {
7716                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7717                         rsurface.modelsvector3f = NULL;
7718                         rsurface.modeltvector3f = NULL;
7719                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7720                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7721                         rsurface.modelvertexmesh = NULL;
7722                         rsurface.modelvertexmeshbuffer = NULL;
7723                         rsurface.modelvertex3fbuffer = NULL;
7724                 }
7725                 else
7726                 {
7727                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7728                         rsurface.modelsvector3f = NULL;
7729                         rsurface.modeltvector3f = NULL;
7730                         rsurface.modelnormal3f = NULL;
7731                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7732                         rsurface.modelvertexmesh = NULL;
7733                         rsurface.modelvertexmeshbuffer = NULL;
7734                         rsurface.modelvertex3fbuffer = NULL;
7735                 }
7736                 rsurface.modelvertex3f_vertexbuffer = 0;
7737                 rsurface.modelvertex3f_bufferoffset = 0;
7738                 rsurface.modelsvector3f_vertexbuffer = 0;
7739                 rsurface.modelsvector3f_bufferoffset = 0;
7740                 rsurface.modeltvector3f_vertexbuffer = 0;
7741                 rsurface.modeltvector3f_bufferoffset = 0;
7742                 rsurface.modelnormal3f_vertexbuffer = 0;
7743                 rsurface.modelnormal3f_bufferoffset = 0;
7744                 rsurface.modelgeneratedvertex = true;
7745         }
7746         else
7747         {
7748                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7749                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7750                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7751                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7752                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7753                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7754                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7755                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7756                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7757                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7758                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7759                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7760                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7761                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7762                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7763                 rsurface.modelgeneratedvertex = false;
7764         }
7765         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7766         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7767         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7768         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7769         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7770         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7771         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7772         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7773         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7774         rsurface.modelelement3i = model->surfmesh.data_element3i;
7775         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7776         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7777         rsurface.modelelement3s = model->surfmesh.data_element3s;
7778         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7779         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7780         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7781         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7782         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7783         rsurface.modelsurfaces = model->data_surfaces;
7784         rsurface.batchgeneratedvertex = false;
7785         rsurface.batchfirstvertex = 0;
7786         rsurface.batchnumvertices = 0;
7787         rsurface.batchfirsttriangle = 0;
7788         rsurface.batchnumtriangles = 0;
7789         rsurface.batchvertex3f  = NULL;
7790         rsurface.batchvertex3f_vertexbuffer = NULL;
7791         rsurface.batchvertex3f_bufferoffset = 0;
7792         rsurface.batchsvector3f = NULL;
7793         rsurface.batchsvector3f_vertexbuffer = NULL;
7794         rsurface.batchsvector3f_bufferoffset = 0;
7795         rsurface.batchtvector3f = NULL;
7796         rsurface.batchtvector3f_vertexbuffer = NULL;
7797         rsurface.batchtvector3f_bufferoffset = 0;
7798         rsurface.batchnormal3f  = NULL;
7799         rsurface.batchnormal3f_vertexbuffer = NULL;
7800         rsurface.batchnormal3f_bufferoffset = 0;
7801         rsurface.batchlightmapcolor4f = NULL;
7802         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7803         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7804         rsurface.batchtexcoordtexture2f = NULL;
7805         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7806         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7807         rsurface.batchtexcoordlightmap2f = NULL;
7808         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7809         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7810         rsurface.batchvertexmesh = NULL;
7811         rsurface.batchvertexmeshbuffer = NULL;
7812         rsurface.batchvertex3fbuffer = NULL;
7813         rsurface.batchelement3i = NULL;
7814         rsurface.batchelement3i_indexbuffer = NULL;
7815         rsurface.batchelement3i_bufferoffset = 0;
7816         rsurface.batchelement3s = NULL;
7817         rsurface.batchelement3s_indexbuffer = NULL;
7818         rsurface.batchelement3s_bufferoffset = 0;
7819         rsurface.passcolor4f = NULL;
7820         rsurface.passcolor4f_vertexbuffer = NULL;
7821         rsurface.passcolor4f_bufferoffset = 0;
7822 }
7823
7824 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)
7825 {
7826         rsurface.entity = r_refdef.scene.worldentity;
7827         rsurface.skeleton = NULL;
7828         rsurface.ent_skinnum = 0;
7829         rsurface.ent_qwskin = -1;
7830         rsurface.ent_shadertime = shadertime;
7831         rsurface.ent_flags = entflags;
7832         rsurface.modelnumvertices = numvertices;
7833         rsurface.modelnumtriangles = numtriangles;
7834         rsurface.matrix = *matrix;
7835         rsurface.inversematrix = *inversematrix;
7836         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7837         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7838         R_EntityMatrix(&rsurface.matrix);
7839         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7840         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7841         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7842         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7843         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7844         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7845         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7846         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7847         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7848         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7849         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7850         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7851         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);
7852         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7853         rsurface.frameblend[0].lerp = 1;
7854         rsurface.ent_alttextures = false;
7855         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7856         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7857         if (wanttangents)
7858         {
7859                 rsurface.modelvertex3f = (float *)vertex3f;
7860                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7861                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7862                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7863         }
7864         else if (wantnormals)
7865         {
7866                 rsurface.modelvertex3f = (float *)vertex3f;
7867                 rsurface.modelsvector3f = NULL;
7868                 rsurface.modeltvector3f = NULL;
7869                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7870         }
7871         else
7872         {
7873                 rsurface.modelvertex3f = (float *)vertex3f;
7874                 rsurface.modelsvector3f = NULL;
7875                 rsurface.modeltvector3f = NULL;
7876                 rsurface.modelnormal3f = NULL;
7877         }
7878         rsurface.modelvertexmesh = NULL;
7879         rsurface.modelvertexmeshbuffer = NULL;
7880         rsurface.modelvertex3fbuffer = NULL;
7881         rsurface.modelvertex3f_vertexbuffer = 0;
7882         rsurface.modelvertex3f_bufferoffset = 0;
7883         rsurface.modelsvector3f_vertexbuffer = 0;
7884         rsurface.modelsvector3f_bufferoffset = 0;
7885         rsurface.modeltvector3f_vertexbuffer = 0;
7886         rsurface.modeltvector3f_bufferoffset = 0;
7887         rsurface.modelnormal3f_vertexbuffer = 0;
7888         rsurface.modelnormal3f_bufferoffset = 0;
7889         rsurface.modelgeneratedvertex = true;
7890         rsurface.modellightmapcolor4f  = (float *)color4f;
7891         rsurface.modellightmapcolor4f_vertexbuffer = 0;
7892         rsurface.modellightmapcolor4f_bufferoffset = 0;
7893         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
7894         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7895         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7896         rsurface.modeltexcoordlightmap2f  = NULL;
7897         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7898         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7899         rsurface.modelelement3i = (int *)element3i;
7900         rsurface.modelelement3i_indexbuffer = NULL;
7901         rsurface.modelelement3i_bufferoffset = 0;
7902         rsurface.modelelement3s = (unsigned short *)element3s;
7903         rsurface.modelelement3s_indexbuffer = NULL;
7904         rsurface.modelelement3s_bufferoffset = 0;
7905         rsurface.modellightmapoffsets = NULL;
7906         rsurface.modelsurfaces = NULL;
7907         rsurface.batchgeneratedvertex = false;
7908         rsurface.batchfirstvertex = 0;
7909         rsurface.batchnumvertices = 0;
7910         rsurface.batchfirsttriangle = 0;
7911         rsurface.batchnumtriangles = 0;
7912         rsurface.batchvertex3f  = NULL;
7913         rsurface.batchvertex3f_vertexbuffer = NULL;
7914         rsurface.batchvertex3f_bufferoffset = 0;
7915         rsurface.batchsvector3f = NULL;
7916         rsurface.batchsvector3f_vertexbuffer = NULL;
7917         rsurface.batchsvector3f_bufferoffset = 0;
7918         rsurface.batchtvector3f = NULL;
7919         rsurface.batchtvector3f_vertexbuffer = NULL;
7920         rsurface.batchtvector3f_bufferoffset = 0;
7921         rsurface.batchnormal3f  = NULL;
7922         rsurface.batchnormal3f_vertexbuffer = NULL;
7923         rsurface.batchnormal3f_bufferoffset = 0;
7924         rsurface.batchlightmapcolor4f = NULL;
7925         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7926         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7927         rsurface.batchtexcoordtexture2f = NULL;
7928         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7929         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7930         rsurface.batchtexcoordlightmap2f = NULL;
7931         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7932         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7933         rsurface.batchvertexmesh = NULL;
7934         rsurface.batchvertexmeshbuffer = NULL;
7935         rsurface.batchvertex3fbuffer = NULL;
7936         rsurface.batchelement3i = NULL;
7937         rsurface.batchelement3i_indexbuffer = NULL;
7938         rsurface.batchelement3i_bufferoffset = 0;
7939         rsurface.batchelement3s = NULL;
7940         rsurface.batchelement3s_indexbuffer = NULL;
7941         rsurface.batchelement3s_bufferoffset = 0;
7942         rsurface.passcolor4f = NULL;
7943         rsurface.passcolor4f_vertexbuffer = NULL;
7944         rsurface.passcolor4f_bufferoffset = 0;
7945
7946         if (rsurface.modelnumvertices && rsurface.modelelement3i)
7947         {
7948                 if ((wantnormals || wanttangents) && !normal3f)
7949                 {
7950                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7951                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7952                 }
7953                 if (wanttangents && !svector3f)
7954                 {
7955                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7956                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7957                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7958                 }
7959         }
7960 }
7961
7962 float RSurf_FogPoint(const float *v)
7963 {
7964         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7965         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7966         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7967         float FogHeightFade = r_refdef.fogheightfade;
7968         float fogfrac;
7969         unsigned int fogmasktableindex;
7970         if (r_refdef.fogplaneviewabove)
7971                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7972         else
7973                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7974         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7975         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7976 }
7977
7978 float RSurf_FogVertex(const float *v)
7979 {
7980         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7981         float FogPlaneViewDist = rsurface.fogplaneviewdist;
7982         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7983         float FogHeightFade = rsurface.fogheightfade;
7984         float fogfrac;
7985         unsigned int fogmasktableindex;
7986         if (r_refdef.fogplaneviewabove)
7987                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7988         else
7989                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7990         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
7991         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7992 }
7993
7994 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
7995 {
7996         int i;
7997         for (i = 0;i < numelements;i++)
7998                 outelement3i[i] = inelement3i[i] + adjust;
7999 }
8000
8001 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8002 extern cvar_t gl_vbo;
8003 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8004 {
8005         int deformindex;
8006         int firsttriangle;
8007         int numtriangles;
8008         int firstvertex;
8009         int endvertex;
8010         int numvertices;
8011         int surfacefirsttriangle;
8012         int surfacenumtriangles;
8013         int surfacefirstvertex;
8014         int surfaceendvertex;
8015         int surfacenumvertices;
8016         int batchnumvertices;
8017         int batchnumtriangles;
8018         int needsupdate;
8019         int i, j;
8020         qboolean gaps;
8021         qboolean dynamicvertex;
8022         float amplitude;
8023         float animpos;
8024         float scale;
8025         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8026         float waveparms[4];
8027         q3shaderinfo_deform_t *deform;
8028         const msurface_t *surface, *firstsurface;
8029         r_vertexmesh_t *vertexmesh;
8030         if (!texturenumsurfaces)
8031                 return;
8032         // find vertex range of this surface batch
8033         gaps = false;
8034         firstsurface = texturesurfacelist[0];
8035         firsttriangle = firstsurface->num_firsttriangle;
8036         batchnumvertices = 0;
8037         batchnumtriangles = 0;
8038         firstvertex = endvertex = firstsurface->num_firstvertex;
8039         for (i = 0;i < texturenumsurfaces;i++)
8040         {
8041                 surface = texturesurfacelist[i];
8042                 if (surface != firstsurface + i)
8043                         gaps = true;
8044                 surfacefirstvertex = surface->num_firstvertex;
8045                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8046                 surfacenumvertices = surface->num_vertices;
8047                 surfacenumtriangles = surface->num_triangles;
8048                 if (firstvertex > surfacefirstvertex)
8049                         firstvertex = surfacefirstvertex;
8050                 if (endvertex < surfaceendvertex)
8051                         endvertex = surfaceendvertex;
8052                 batchnumvertices += surfacenumvertices;
8053                 batchnumtriangles += surfacenumtriangles;
8054         }
8055
8056         // we now know the vertex range used, and if there are any gaps in it
8057         rsurface.batchfirstvertex = firstvertex;
8058         rsurface.batchnumvertices = endvertex - firstvertex;
8059         rsurface.batchfirsttriangle = firsttriangle;
8060         rsurface.batchnumtriangles = batchnumtriangles;
8061
8062         // this variable holds flags for which properties have been updated that
8063         // may require regenerating vertexmesh array...
8064         needsupdate = 0;
8065
8066         // check if any dynamic vertex processing must occur
8067         dynamicvertex = false;
8068
8069         // if there is a chance of animated vertex colors, it's a dynamic batch
8070         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8071         {
8072                 dynamicvertex = true;
8073                 batchneed |= BATCHNEED_NOGAPS;
8074                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8075         }
8076
8077         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8078         {
8079                 switch (deform->deform)
8080                 {
8081                 default:
8082                 case Q3DEFORM_PROJECTIONSHADOW:
8083                 case Q3DEFORM_TEXT0:
8084                 case Q3DEFORM_TEXT1:
8085                 case Q3DEFORM_TEXT2:
8086                 case Q3DEFORM_TEXT3:
8087                 case Q3DEFORM_TEXT4:
8088                 case Q3DEFORM_TEXT5:
8089                 case Q3DEFORM_TEXT6:
8090                 case Q3DEFORM_TEXT7:
8091                 case Q3DEFORM_NONE:
8092                         break;
8093                 case Q3DEFORM_AUTOSPRITE:
8094                         dynamicvertex = true;
8095                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8096                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8097                         break;
8098                 case Q3DEFORM_AUTOSPRITE2:
8099                         dynamicvertex = true;
8100                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8101                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8102                         break;
8103                 case Q3DEFORM_NORMAL:
8104                         dynamicvertex = true;
8105                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8106                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8107                         break;
8108                 case Q3DEFORM_WAVE:
8109                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8110                                 break; // if wavefunc is a nop, ignore this transform
8111                         dynamicvertex = true;
8112                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8113                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8114                         break;
8115                 case Q3DEFORM_BULGE:
8116                         dynamicvertex = true;
8117                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8118                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8119                         break;
8120                 case Q3DEFORM_MOVE:
8121                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8122                                 break; // if wavefunc is a nop, ignore this transform
8123                         dynamicvertex = true;
8124                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8125                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8126                         break;
8127                 }
8128         }
8129         switch(rsurface.texture->tcgen.tcgen)
8130         {
8131         default:
8132         case Q3TCGEN_TEXTURE:
8133                 break;
8134         case Q3TCGEN_LIGHTMAP:
8135                 dynamicvertex = true;
8136                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8137                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8138                 break;
8139         case Q3TCGEN_VECTOR:
8140                 dynamicvertex = true;
8141                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8142                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8143                 break;
8144         case Q3TCGEN_ENVIRONMENT:
8145                 dynamicvertex = true;
8146                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8147                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8148                 break;
8149         }
8150         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8151         {
8152                 dynamicvertex = true;
8153                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8154                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8155         }
8156
8157         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8158         {
8159                 dynamicvertex = true;
8160                 batchneed |= BATCHNEED_NOGAPS;
8161                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8162         }
8163
8164         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8165         {
8166                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8167                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8168                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8169                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8170                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8171                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8172                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8173         }
8174
8175         // when the model data has no vertex buffer (dynamic mesh), we need to
8176         // eliminate gaps
8177         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8178                 batchneed |= BATCHNEED_NOGAPS;
8179
8180         // if needsupdate, we have to do a dynamic vertex batch for sure
8181         if (needsupdate & batchneed)
8182                 dynamicvertex = true;
8183
8184         // see if we need to build vertexmesh from arrays
8185         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8186                 dynamicvertex = true;
8187
8188         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8189         // also some drivers strongly dislike firstvertex
8190         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8191                 dynamicvertex = true;
8192
8193         rsurface.batchvertex3f = rsurface.modelvertex3f;
8194         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8195         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8196         rsurface.batchsvector3f = rsurface.modelsvector3f;
8197         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8198         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8199         rsurface.batchtvector3f = rsurface.modeltvector3f;
8200         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8201         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8202         rsurface.batchnormal3f = rsurface.modelnormal3f;
8203         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8204         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8205         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8206         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8207         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8208         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8209         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8210         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8211         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8212         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8213         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8214         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8215         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8216         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8217         rsurface.batchelement3i = rsurface.modelelement3i;
8218         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8219         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8220         rsurface.batchelement3s = rsurface.modelelement3s;
8221         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8222         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8223
8224         // if any dynamic vertex processing has to occur in software, we copy the
8225         // entire surface list together before processing to rebase the vertices
8226         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8227         //
8228         // if any gaps exist and we do not have a static vertex buffer, we have to
8229         // copy the surface list together to avoid wasting upload bandwidth on the
8230         // vertices in the gaps.
8231         //
8232         // if gaps exist and we have a static vertex buffer, we still have to
8233         // combine the index buffer ranges into one dynamic index buffer.
8234         //
8235         // in all cases we end up with data that can be drawn in one call.
8236
8237         if (!dynamicvertex)
8238         {
8239                 // static vertex data, just set pointers...
8240                 rsurface.batchgeneratedvertex = false;
8241                 // if there are gaps, we want to build a combined index buffer,
8242                 // otherwise use the original static buffer with an appropriate offset
8243                 if (gaps)
8244                 {
8245                         // build a new triangle elements array for this batch
8246                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8247                         rsurface.batchfirsttriangle = 0;
8248                         numtriangles = 0;
8249                         for (i = 0;i < texturenumsurfaces;i++)
8250                         {
8251                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8252                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8253                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8254                                 numtriangles += surfacenumtriangles;
8255                         }
8256                         rsurface.batchelement3i_indexbuffer = NULL;
8257                         rsurface.batchelement3i_bufferoffset = 0;
8258                         rsurface.batchelement3s = NULL;
8259                         rsurface.batchelement3s_indexbuffer = NULL;
8260                         rsurface.batchelement3s_bufferoffset = 0;
8261                         if (endvertex <= 65536)
8262                         {
8263                                 // make a 16bit (unsigned short) index array if possible
8264                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8265                                 for (i = 0;i < numtriangles*3;i++)
8266                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8267                         }
8268                 }
8269                 return;
8270         }
8271
8272         // something needs software processing, do it for real...
8273         // we only directly handle separate array data in this case and then
8274         // generate interleaved data if needed...
8275         rsurface.batchgeneratedvertex = true;
8276
8277         // now copy the vertex data into a combined array and make an index array
8278         // (this is what Quake3 does all the time)
8279         //if (gaps || rsurface.batchfirstvertex)
8280         {
8281                 rsurface.batchvertex3fbuffer = NULL;
8282                 rsurface.batchvertexmesh = NULL;
8283                 rsurface.batchvertexmeshbuffer = NULL;
8284                 rsurface.batchvertex3f = NULL;
8285                 rsurface.batchvertex3f_vertexbuffer = NULL;
8286                 rsurface.batchvertex3f_bufferoffset = 0;
8287                 rsurface.batchsvector3f = NULL;
8288                 rsurface.batchsvector3f_vertexbuffer = NULL;
8289                 rsurface.batchsvector3f_bufferoffset = 0;
8290                 rsurface.batchtvector3f = NULL;
8291                 rsurface.batchtvector3f_vertexbuffer = NULL;
8292                 rsurface.batchtvector3f_bufferoffset = 0;
8293                 rsurface.batchnormal3f = NULL;
8294                 rsurface.batchnormal3f_vertexbuffer = NULL;
8295                 rsurface.batchnormal3f_bufferoffset = 0;
8296                 rsurface.batchlightmapcolor4f = NULL;
8297                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8298                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8299                 rsurface.batchtexcoordtexture2f = NULL;
8300                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8301                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8302                 rsurface.batchtexcoordlightmap2f = NULL;
8303                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8304                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8305                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8306                 rsurface.batchelement3i_indexbuffer = NULL;
8307                 rsurface.batchelement3i_bufferoffset = 0;
8308                 rsurface.batchelement3s = NULL;
8309                 rsurface.batchelement3s_indexbuffer = NULL;
8310                 rsurface.batchelement3s_bufferoffset = 0;
8311                 // we'll only be setting up certain arrays as needed
8312                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8313                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8314                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8315                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8316                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8317                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8318                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8319                 {
8320                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8321                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8322                 }
8323                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8324                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8325                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8326                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8327                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8328                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8329                 numvertices = 0;
8330                 numtriangles = 0;
8331                 for (i = 0;i < texturenumsurfaces;i++)
8332                 {
8333                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8334                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8335                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8336                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8337                         // copy only the data requested
8338                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8339                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8340                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8341                         {
8342                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8343                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8344                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8345                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8346                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8347                                 {
8348                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8349                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8350                                 }
8351                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8352                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8353                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8354                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8355                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8356                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8357                         }
8358                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8359                         numvertices += surfacenumvertices;
8360                         numtriangles += surfacenumtriangles;
8361                 }
8362
8363                 // generate a 16bit index array as well if possible
8364                 // (in general, dynamic batches fit)
8365                 if (numvertices <= 65536)
8366                 {
8367                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8368                         for (i = 0;i < numtriangles*3;i++)
8369                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8370                 }
8371
8372                 // since we've copied everything, the batch now starts at 0
8373                 rsurface.batchfirstvertex = 0;
8374                 rsurface.batchnumvertices = batchnumvertices;
8375                 rsurface.batchfirsttriangle = 0;
8376                 rsurface.batchnumtriangles = batchnumtriangles;
8377         }
8378
8379         // q1bsp surfaces rendered in vertex color mode have to have colors
8380         // calculated based on lightstyles
8381         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8382         {
8383                 // generate color arrays for the surfaces in this list
8384                 int c[4];
8385                 int scale;
8386                 int size3;
8387                 const int *offsets;
8388                 const unsigned char *lm;
8389                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8390                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8391                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8392                 numvertices = 0;
8393                 for (i = 0;i < texturenumsurfaces;i++)
8394                 {
8395                         surface = texturesurfacelist[i];
8396                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8397                         surfacenumvertices = surface->num_vertices;
8398                         if (surface->lightmapinfo->samples)
8399                         {
8400                                 for (j = 0;j < surfacenumvertices;j++)
8401                                 {
8402                                         lm = surface->lightmapinfo->samples + offsets[j];
8403                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8404                                         VectorScale(lm, scale, c);
8405                                         if (surface->lightmapinfo->styles[1] != 255)
8406                                         {
8407                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8408                                                 lm += size3;
8409                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8410                                                 VectorMA(c, scale, lm, c);
8411                                                 if (surface->lightmapinfo->styles[2] != 255)
8412                                                 {
8413                                                         lm += size3;
8414                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8415                                                         VectorMA(c, scale, lm, c);
8416                                                         if (surface->lightmapinfo->styles[3] != 255)
8417                                                         {
8418                                                                 lm += size3;
8419                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8420                                                                 VectorMA(c, scale, lm, c);
8421                                                         }
8422                                                 }
8423                                         }
8424                                         c[0] >>= 7;
8425                                         c[1] >>= 7;
8426                                         c[2] >>= 7;
8427                                         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);
8428                                         numvertices++;
8429                                 }
8430                         }
8431                         else
8432                         {
8433                                 for (j = 0;j < surfacenumvertices;j++)
8434                                 {
8435                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8436                                         numvertices++;
8437                                 }
8438                         }
8439                 }
8440         }
8441
8442         // if vertices are deformed (sprite flares and things in maps, possibly
8443         // water waves, bulges and other deformations), modify the copied vertices
8444         // in place
8445         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8446         {
8447                 switch (deform->deform)
8448                 {
8449                 default:
8450                 case Q3DEFORM_PROJECTIONSHADOW:
8451                 case Q3DEFORM_TEXT0:
8452                 case Q3DEFORM_TEXT1:
8453                 case Q3DEFORM_TEXT2:
8454                 case Q3DEFORM_TEXT3:
8455                 case Q3DEFORM_TEXT4:
8456                 case Q3DEFORM_TEXT5:
8457                 case Q3DEFORM_TEXT6:
8458                 case Q3DEFORM_TEXT7:
8459                 case Q3DEFORM_NONE:
8460                         break;
8461                 case Q3DEFORM_AUTOSPRITE:
8462                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8463                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8464                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8465                         VectorNormalize(newforward);
8466                         VectorNormalize(newright);
8467                         VectorNormalize(newup);
8468 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8469 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8470 //                      rsurface.batchvertex3f_bufferoffset = 0;
8471 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8472 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8473 //                      rsurface.batchsvector3f_bufferoffset = 0;
8474 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8475 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8476 //                      rsurface.batchtvector3f_bufferoffset = 0;
8477 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8478 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8479 //                      rsurface.batchnormal3f_bufferoffset = 0;
8480                         // a single autosprite surface can contain multiple sprites...
8481                         for (j = 0;j < batchnumvertices - 3;j += 4)
8482                         {
8483                                 VectorClear(center);
8484                                 for (i = 0;i < 4;i++)
8485                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8486                                 VectorScale(center, 0.25f, center);
8487                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8488                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8489                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8490                                 for (i = 0;i < 4;i++)
8491                                 {
8492                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8493                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8494                                 }
8495                         }
8496                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8497                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8498                         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);
8499                         break;
8500                 case Q3DEFORM_AUTOSPRITE2:
8501                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8502                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8503                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8504                         VectorNormalize(newforward);
8505                         VectorNormalize(newright);
8506                         VectorNormalize(newup);
8507 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8508 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8509 //                      rsurface.batchvertex3f_bufferoffset = 0;
8510                         {
8511                                 const float *v1, *v2;
8512                                 vec3_t start, end;
8513                                 float f, l;
8514                                 struct
8515                                 {
8516                                         float length2;
8517                                         const float *v1;
8518                                         const float *v2;
8519                                 }
8520                                 shortest[2];
8521                                 memset(shortest, 0, sizeof(shortest));
8522                                 // a single autosprite surface can contain multiple sprites...
8523                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8524                                 {
8525                                         VectorClear(center);
8526                                         for (i = 0;i < 4;i++)
8527                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8528                                         VectorScale(center, 0.25f, center);
8529                                         // find the two shortest edges, then use them to define the
8530                                         // axis vectors for rotating around the central axis
8531                                         for (i = 0;i < 6;i++)
8532                                         {
8533                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8534                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8535                                                 l = VectorDistance2(v1, v2);
8536                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8537                                                 if (v1[2] != v2[2])
8538                                                         l += (1.0f / 1024.0f);
8539                                                 if (shortest[0].length2 > l || i == 0)
8540                                                 {
8541                                                         shortest[1] = shortest[0];
8542                                                         shortest[0].length2 = l;
8543                                                         shortest[0].v1 = v1;
8544                                                         shortest[0].v2 = v2;
8545                                                 }
8546                                                 else if (shortest[1].length2 > l || i == 1)
8547                                                 {
8548                                                         shortest[1].length2 = l;
8549                                                         shortest[1].v1 = v1;
8550                                                         shortest[1].v2 = v2;
8551                                                 }
8552                                         }
8553                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8554                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8555                                         // this calculates the right vector from the shortest edge
8556                                         // and the up vector from the edge midpoints
8557                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8558                                         VectorNormalize(right);
8559                                         VectorSubtract(end, start, up);
8560                                         VectorNormalize(up);
8561                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8562                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8563                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8564                                         VectorNegate(forward, forward);
8565                                         VectorReflect(forward, 0, up, forward);
8566                                         VectorNormalize(forward);
8567                                         CrossProduct(up, forward, newright);
8568                                         VectorNormalize(newright);
8569                                         // rotate the quad around the up axis vector, this is made
8570                                         // especially easy by the fact we know the quad is flat,
8571                                         // so we only have to subtract the center position and
8572                                         // measure distance along the right vector, and then
8573                                         // multiply that by the newright vector and add back the
8574                                         // center position
8575                                         // we also need to subtract the old position to undo the
8576                                         // displacement from the center, which we do with a
8577                                         // DotProduct, the subtraction/addition of center is also
8578                                         // optimized into DotProducts here
8579                                         l = DotProduct(right, center);
8580                                         for (i = 0;i < 4;i++)
8581                                         {
8582                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8583                                                 f = DotProduct(right, v1) - l;
8584                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8585                                         }
8586                                 }
8587                         }
8588                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8589                         {
8590 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8591 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8592 //                              rsurface.batchnormal3f_bufferoffset = 0;
8593                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8594                         }
8595                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8596                         {
8597 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8598 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8599 //                              rsurface.batchsvector3f_bufferoffset = 0;
8600 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8601 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8602 //                              rsurface.batchtvector3f_bufferoffset = 0;
8603                                 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);
8604                         }
8605                         break;
8606                 case Q3DEFORM_NORMAL:
8607                         // deform the normals to make reflections wavey
8608                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8609                         rsurface.batchnormal3f_vertexbuffer = NULL;
8610                         rsurface.batchnormal3f_bufferoffset = 0;
8611                         for (j = 0;j < batchnumvertices;j++)
8612                         {
8613                                 float vertex[3];
8614                                 float *normal = rsurface.batchnormal3f + 3*j;
8615                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8616                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8617                                 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]);
8618                                 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]);
8619                                 VectorNormalize(normal);
8620                         }
8621                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8622                         {
8623 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8624 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8625 //                              rsurface.batchsvector3f_bufferoffset = 0;
8626 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8627 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8628 //                              rsurface.batchtvector3f_bufferoffset = 0;
8629                                 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);
8630                         }
8631                         break;
8632                 case Q3DEFORM_WAVE:
8633                         // deform vertex array to make wavey water and flags and such
8634                         waveparms[0] = deform->waveparms[0];
8635                         waveparms[1] = deform->waveparms[1];
8636                         waveparms[2] = deform->waveparms[2];
8637                         waveparms[3] = deform->waveparms[3];
8638                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8639                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8640                         // this is how a divisor of vertex influence on deformation
8641                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8642                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8643 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8644 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8645 //                      rsurface.batchvertex3f_bufferoffset = 0;
8646 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8647 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8648 //                      rsurface.batchnormal3f_bufferoffset = 0;
8649                         for (j = 0;j < batchnumvertices;j++)
8650                         {
8651                                 // if the wavefunc depends on time, evaluate it per-vertex
8652                                 if (waveparms[3])
8653                                 {
8654                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8655                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8656                                 }
8657                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8658                         }
8659                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8660                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8661                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8662                         {
8663 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8664 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8665 //                              rsurface.batchsvector3f_bufferoffset = 0;
8666 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8667 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8668 //                              rsurface.batchtvector3f_bufferoffset = 0;
8669                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8670                         }
8671                         break;
8672                 case Q3DEFORM_BULGE:
8673                         // deform vertex array to make the surface have moving bulges
8674 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8675 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8676 //                      rsurface.batchvertex3f_bufferoffset = 0;
8677 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8678 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8679 //                      rsurface.batchnormal3f_bufferoffset = 0;
8680                         for (j = 0;j < batchnumvertices;j++)
8681                         {
8682                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8683                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8684                         }
8685                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8686                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8687                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8688                         {
8689 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8690 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8691 //                              rsurface.batchsvector3f_bufferoffset = 0;
8692 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8693 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8694 //                              rsurface.batchtvector3f_bufferoffset = 0;
8695                                 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);
8696                         }
8697                         break;
8698                 case Q3DEFORM_MOVE:
8699                         // deform vertex array
8700                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8701                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8702                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8703                         VectorScale(deform->parms, scale, waveparms);
8704 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8705 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8706 //                      rsurface.batchvertex3f_bufferoffset = 0;
8707                         for (j = 0;j < batchnumvertices;j++)
8708                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8709                         break;
8710                 }
8711         }
8712
8713         // generate texcoords based on the chosen texcoord source
8714         switch(rsurface.texture->tcgen.tcgen)
8715         {
8716         default:
8717         case Q3TCGEN_TEXTURE:
8718                 break;
8719         case Q3TCGEN_LIGHTMAP:
8720 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8721 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8722 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8723                 if (rsurface.batchtexcoordlightmap2f)
8724                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8725                 break;
8726         case Q3TCGEN_VECTOR:
8727 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8728 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8729 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8730                 for (j = 0;j < batchnumvertices;j++)
8731                 {
8732                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8733                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8734                 }
8735                 break;
8736         case Q3TCGEN_ENVIRONMENT:
8737                 // make environment reflections using a spheremap
8738                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8739                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8740                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8741                 for (j = 0;j < batchnumvertices;j++)
8742                 {
8743                         // identical to Q3A's method, but executed in worldspace so
8744                         // carried models can be shiny too
8745
8746                         float viewer[3], d, reflected[3], worldreflected[3];
8747
8748                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8749                         // VectorNormalize(viewer);
8750
8751                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8752
8753                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8754                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8755                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8756                         // note: this is proportinal to viewer, so we can normalize later
8757
8758                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8759                         VectorNormalize(worldreflected);
8760
8761                         // note: this sphere map only uses world x and z!
8762                         // so positive and negative y will LOOK THE SAME.
8763                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8764                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8765                 }
8766                 break;
8767         }
8768         // the only tcmod that needs software vertex processing is turbulent, so
8769         // check for it here and apply the changes if needed
8770         // and we only support that as the first one
8771         // (handling a mixture of turbulent and other tcmods would be problematic
8772         //  without punting it entirely to a software path)
8773         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8774         {
8775                 amplitude = rsurface.texture->tcmods[0].parms[1];
8776                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8777 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8778 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8779 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8780                 for (j = 0;j < batchnumvertices;j++)
8781                 {
8782                         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);
8783                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8784                 }
8785         }
8786
8787         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8788         {
8789                 // convert the modified arrays to vertex structs
8790 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8791 //              rsurface.batchvertexmeshbuffer = NULL;
8792                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8793                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8794                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8795                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8796                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8797                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8798                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8799                 {
8800                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8801                         {
8802                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8803                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8804                         }
8805                 }
8806                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8807                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8808                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8809                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8810                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8811                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8812                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8813                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8814                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8815         }
8816 }
8817
8818 void RSurf_DrawBatch(void)
8819 {
8820         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8821         // through the pipeline, killing it earlier in the pipeline would have
8822         // per-surface overhead rather than per-batch overhead, so it's best to
8823         // reject it here, before it hits glDraw.
8824         if (rsurface.batchnumtriangles == 0)
8825                 return;
8826 #if 0
8827         // batch debugging code
8828         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8829         {
8830                 int i;
8831                 int j;
8832                 int c;
8833                 const int *e;
8834                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8835                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8836                 {
8837                         c = e[i];
8838                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8839                         {
8840                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8841                                 {
8842                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8843                                                 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);
8844                                         break;
8845                                 }
8846                         }
8847                 }
8848         }
8849 #endif
8850         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);
8851 }
8852
8853 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8854 {
8855         // pick the closest matching water plane
8856         int planeindex, vertexindex, bestplaneindex = -1;
8857         float d, bestd;
8858         vec3_t vert;
8859         const float *v;
8860         r_waterstate_waterplane_t *p;
8861         qboolean prepared = false;
8862         bestd = 0;
8863         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8864         {
8865                 if(p->camera_entity != rsurface.texture->camera_entity)
8866                         continue;
8867                 d = 0;
8868                 if(!prepared)
8869                 {
8870                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8871                         prepared = true;
8872                         if(rsurface.batchnumvertices == 0)
8873                                 break;
8874                 }
8875                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8876                 {
8877                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8878                         d += fabs(PlaneDiff(vert, &p->plane));
8879                 }
8880                 if (bestd > d || bestplaneindex < 0)
8881                 {
8882                         bestd = d;
8883                         bestplaneindex = planeindex;
8884                 }
8885         }
8886         return bestplaneindex;
8887         // NOTE: this MAY return a totally unrelated water plane; we can ignore
8888         // this situation though, as it might be better to render single larger
8889         // batches with useless stuff (backface culled for example) than to
8890         // render multiple smaller batches
8891 }
8892
8893 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8894 {
8895         int i;
8896         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8897         rsurface.passcolor4f_vertexbuffer = 0;
8898         rsurface.passcolor4f_bufferoffset = 0;
8899         for (i = 0;i < rsurface.batchnumvertices;i++)
8900                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8901 }
8902
8903 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8904 {
8905         int i;
8906         float f;
8907         const float *v;
8908         const float *c;
8909         float *c2;
8910         if (rsurface.passcolor4f)
8911         {
8912                 // generate color arrays
8913                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8914                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8915                 rsurface.passcolor4f_vertexbuffer = 0;
8916                 rsurface.passcolor4f_bufferoffset = 0;
8917                 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)
8918                 {
8919                         f = RSurf_FogVertex(v);
8920                         c2[0] = c[0] * f;
8921                         c2[1] = c[1] * f;
8922                         c2[2] = c[2] * f;
8923                         c2[3] = c[3];
8924                 }
8925         }
8926         else
8927         {
8928                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8929                 rsurface.passcolor4f_vertexbuffer = 0;
8930                 rsurface.passcolor4f_bufferoffset = 0;
8931                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8932                 {
8933                         f = RSurf_FogVertex(v);
8934                         c2[0] = f;
8935                         c2[1] = f;
8936                         c2[2] = f;
8937                         c2[3] = 1;
8938                 }
8939         }
8940 }
8941
8942 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8943 {
8944         int i;
8945         float f;
8946         const float *v;
8947         const float *c;
8948         float *c2;
8949         if (!rsurface.passcolor4f)
8950                 return;
8951         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8952         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8953         rsurface.passcolor4f_vertexbuffer = 0;
8954         rsurface.passcolor4f_bufferoffset = 0;
8955         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)
8956         {
8957                 f = RSurf_FogVertex(v);
8958                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8959                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8960                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8961                 c2[3] = c[3];
8962         }
8963 }
8964
8965 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
8966 {
8967         int i;
8968         const float *c;
8969         float *c2;
8970         if (!rsurface.passcolor4f)
8971                 return;
8972         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8973         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8974         rsurface.passcolor4f_vertexbuffer = 0;
8975         rsurface.passcolor4f_bufferoffset = 0;
8976         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
8977         {
8978                 c2[0] = c[0] * r;
8979                 c2[1] = c[1] * g;
8980                 c2[2] = c[2] * b;
8981                 c2[3] = c[3] * a;
8982         }
8983 }
8984
8985 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
8986 {
8987         int i;
8988         const float *c;
8989         float *c2;
8990         if (!rsurface.passcolor4f)
8991                 return;
8992         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8993         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8994         rsurface.passcolor4f_vertexbuffer = 0;
8995         rsurface.passcolor4f_bufferoffset = 0;
8996         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
8997         {
8998                 c2[0] = c[0] + r_refdef.scene.ambient;
8999                 c2[1] = c[1] + r_refdef.scene.ambient;
9000                 c2[2] = c[2] + r_refdef.scene.ambient;
9001                 c2[3] = c[3];
9002         }
9003 }
9004
9005 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9006 {
9007         // TODO: optimize
9008         rsurface.passcolor4f = NULL;
9009         rsurface.passcolor4f_vertexbuffer = 0;
9010         rsurface.passcolor4f_bufferoffset = 0;
9011         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9012         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9013         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9014         GL_Color(r, g, b, a);
9015         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9016         RSurf_DrawBatch();
9017 }
9018
9019 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9020 {
9021         // TODO: optimize applyfog && applycolor case
9022         // just apply fog if necessary, and tint the fog color array if necessary
9023         rsurface.passcolor4f = NULL;
9024         rsurface.passcolor4f_vertexbuffer = 0;
9025         rsurface.passcolor4f_bufferoffset = 0;
9026         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9027         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9028         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9029         GL_Color(r, g, b, a);
9030         RSurf_DrawBatch();
9031 }
9032
9033 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9034 {
9035         // TODO: optimize
9036         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9037         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9038         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9039         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9040         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9041         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9042         GL_Color(r, g, b, a);
9043         RSurf_DrawBatch();
9044 }
9045
9046 static void RSurf_DrawBatch_GL11_ClampColor(void)
9047 {
9048         int i;
9049         const float *c1;
9050         float *c2;
9051         if (!rsurface.passcolor4f)
9052                 return;
9053         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9054         {
9055                 c2[0] = bound(0.0f, c1[0], 1.0f);
9056                 c2[1] = bound(0.0f, c1[1], 1.0f);
9057                 c2[2] = bound(0.0f, c1[2], 1.0f);
9058                 c2[3] = bound(0.0f, c1[3], 1.0f);
9059         }
9060 }
9061
9062 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9063 {
9064         int i;
9065         float f;
9066         const float *v;
9067         const float *n;
9068         float *c;
9069         //vec3_t eyedir;
9070
9071         // fake shading
9072         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9073         rsurface.passcolor4f_vertexbuffer = 0;
9074         rsurface.passcolor4f_bufferoffset = 0;
9075         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)
9076         {
9077                 f = -DotProduct(r_refdef.view.forward, n);
9078                 f = max(0, f);
9079                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9080                 f *= r_refdef.lightmapintensity;
9081                 Vector4Set(c, f, f, f, 1);
9082         }
9083 }
9084
9085 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9086 {
9087         RSurf_DrawBatch_GL11_ApplyFakeLight();
9088         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9089         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9090         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9091         GL_Color(r, g, b, a);
9092         RSurf_DrawBatch();
9093 }
9094
9095 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9096 {
9097         int i;
9098         float f;
9099         float alpha;
9100         const float *v;
9101         const float *n;
9102         float *c;
9103         vec3_t ambientcolor;
9104         vec3_t diffusecolor;
9105         vec3_t lightdir;
9106         // TODO: optimize
9107         // model lighting
9108         VectorCopy(rsurface.modellight_lightdir, lightdir);
9109         f = 0.5f * r_refdef.lightmapintensity;
9110         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9111         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9112         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9113         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9114         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9115         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9116         alpha = *a;
9117         if (VectorLength2(diffusecolor) > 0)
9118         {
9119                 // q3-style directional shading
9120                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9121                 rsurface.passcolor4f_vertexbuffer = 0;
9122                 rsurface.passcolor4f_bufferoffset = 0;
9123                 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)
9124                 {
9125                         if ((f = DotProduct(n, lightdir)) > 0)
9126                                 VectorMA(ambientcolor, f, diffusecolor, c);
9127                         else
9128                                 VectorCopy(ambientcolor, c);
9129                         c[3] = alpha;
9130                 }
9131                 *r = 1;
9132                 *g = 1;
9133                 *b = 1;
9134                 *a = 1;
9135                 *applycolor = false;
9136         }
9137         else
9138         {
9139                 *r = ambientcolor[0];
9140                 *g = ambientcolor[1];
9141                 *b = ambientcolor[2];
9142                 rsurface.passcolor4f = NULL;
9143                 rsurface.passcolor4f_vertexbuffer = 0;
9144                 rsurface.passcolor4f_bufferoffset = 0;
9145         }
9146 }
9147
9148 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9149 {
9150         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9151         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9152         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9153         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9154         GL_Color(r, g, b, a);
9155         RSurf_DrawBatch();
9156 }
9157
9158 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9159 {
9160         int i;
9161         float f;
9162         const float *v;
9163         float *c;
9164         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9165         {
9166                 f = 1 - RSurf_FogVertex(v);
9167                 c[0] = r;
9168                 c[1] = g;
9169                 c[2] = b;
9170                 c[3] = f * a;
9171         }
9172 }
9173
9174 void RSurf_SetupDepthAndCulling(void)
9175 {
9176         // submodels are biased to avoid z-fighting with world surfaces that they
9177         // may be exactly overlapping (avoids z-fighting artifacts on certain
9178         // doors and things in Quake maps)
9179         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9180         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9181         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9182         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9183 }
9184
9185 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9186 {
9187         // transparent sky would be ridiculous
9188         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9189                 return;
9190         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9191         skyrenderlater = true;
9192         RSurf_SetupDepthAndCulling();
9193         GL_DepthMask(true);
9194         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9195         // skymasking on them, and Quake3 never did sky masking (unlike
9196         // software Quake and software Quake2), so disable the sky masking
9197         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9198         // and skymasking also looks very bad when noclipping outside the
9199         // level, so don't use it then either.
9200         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9201         {
9202                 R_Mesh_ResetTextureState();
9203                 if (skyrendermasked)
9204                 {
9205                         R_SetupShader_DepthOrShadow();
9206                         // depth-only (masking)
9207                         GL_ColorMask(0,0,0,0);
9208                         // just to make sure that braindead drivers don't draw
9209                         // anything despite that colormask...
9210                         GL_BlendFunc(GL_ZERO, GL_ONE);
9211                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9212                         if (rsurface.batchvertex3fbuffer)
9213                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9214                         else
9215                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9216                 }
9217                 else
9218                 {
9219                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9220                         // fog sky
9221                         GL_BlendFunc(GL_ONE, GL_ZERO);
9222                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9223                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9224                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9225                 }
9226                 RSurf_DrawBatch();
9227                 if (skyrendermasked)
9228                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9229         }
9230         R_Mesh_ResetTextureState();
9231         GL_Color(1, 1, 1, 1);
9232 }
9233
9234 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9235 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9236 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9237 {
9238         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9239                 return;
9240         if (prepass)
9241         {
9242                 // render screenspace normalmap to texture
9243                 GL_DepthMask(true);
9244                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9245                 RSurf_DrawBatch();
9246                 return;
9247         }
9248
9249         // bind lightmap texture
9250
9251         // water/refraction/reflection/camera surfaces have to be handled specially
9252         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9253         {
9254                 int start, end, startplaneindex;
9255                 for (start = 0;start < texturenumsurfaces;start = end)
9256                 {
9257                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9258                         if(startplaneindex < 0)
9259                         {
9260                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9261                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9262                                 end = start + 1;
9263                                 continue;
9264                         }
9265                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9266                                 ;
9267                         // now that we have a batch using the same planeindex, render it
9268                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9269                         {
9270                                 // render water or distortion background
9271                                 GL_DepthMask(true);
9272                                 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));
9273                                 RSurf_DrawBatch();
9274                                 // blend surface on top
9275                                 GL_DepthMask(false);
9276                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9277                                 RSurf_DrawBatch();
9278                         }
9279                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9280                         {
9281                                 // render surface with reflection texture as input
9282                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9283                                 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));
9284                                 RSurf_DrawBatch();
9285                         }
9286                 }
9287                 return;
9288         }
9289
9290         // render surface batch normally
9291         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9292         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9293         RSurf_DrawBatch();
9294 }
9295
9296 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9297 {
9298         // OpenGL 1.3 path - anything not completely ancient
9299         qboolean applycolor;
9300         qboolean applyfog;
9301         int layerindex;
9302         const texturelayer_t *layer;
9303         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);
9304         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9305
9306         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9307         {
9308                 vec4_t layercolor;
9309                 int layertexrgbscale;
9310                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9311                 {
9312                         if (layerindex == 0)
9313                                 GL_AlphaTest(true);
9314                         else
9315                         {
9316                                 GL_AlphaTest(false);
9317                                 GL_DepthFunc(GL_EQUAL);
9318                         }
9319                 }
9320                 GL_DepthMask(layer->depthmask && writedepth);
9321                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9322                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9323                 {
9324                         layertexrgbscale = 4;
9325                         VectorScale(layer->color, 0.25f, layercolor);
9326                 }
9327                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9328                 {
9329                         layertexrgbscale = 2;
9330                         VectorScale(layer->color, 0.5f, layercolor);
9331                 }
9332                 else
9333                 {
9334                         layertexrgbscale = 1;
9335                         VectorScale(layer->color, 1.0f, layercolor);
9336                 }
9337                 layercolor[3] = layer->color[3];
9338                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9339                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9340                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9341                 switch (layer->type)
9342                 {
9343                 case TEXTURELAYERTYPE_LITTEXTURE:
9344                         // single-pass lightmapped texture with 2x rgbscale
9345                         R_Mesh_TexBind(0, r_texture_white);
9346                         R_Mesh_TexMatrix(0, NULL);
9347                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9348                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9349                         R_Mesh_TexBind(1, layer->texture);
9350                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9351                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9352                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9353                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9354                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9355                         else if (FAKELIGHT_ENABLED)
9356                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9357                         else if (rsurface.uselightmaptexture)
9358                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9359                         else
9360                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9361                         break;
9362                 case TEXTURELAYERTYPE_TEXTURE:
9363                         // singletexture unlit texture with transparency support
9364                         R_Mesh_TexBind(0, layer->texture);
9365                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9366                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9367                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9368                         R_Mesh_TexBind(1, 0);
9369                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9370                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9371                         break;
9372                 case TEXTURELAYERTYPE_FOG:
9373                         // singletexture fogging
9374                         if (layer->texture)
9375                         {
9376                                 R_Mesh_TexBind(0, layer->texture);
9377                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9378                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9379                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9380                         }
9381                         else
9382                         {
9383                                 R_Mesh_TexBind(0, 0);
9384                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9385                         }
9386                         R_Mesh_TexBind(1, 0);
9387                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9388                         // generate a color array for the fog pass
9389                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9390                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9391                         RSurf_DrawBatch();
9392                         break;
9393                 default:
9394                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9395                 }
9396         }
9397         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9398         {
9399                 GL_DepthFunc(GL_LEQUAL);
9400                 GL_AlphaTest(false);
9401         }
9402 }
9403
9404 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9405 {
9406         // OpenGL 1.1 - crusty old voodoo path
9407         qboolean applyfog;
9408         int layerindex;
9409         const texturelayer_t *layer;
9410         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);
9411         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9412
9413         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9414         {
9415                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9416                 {
9417                         if (layerindex == 0)
9418                                 GL_AlphaTest(true);
9419                         else
9420                         {
9421                                 GL_AlphaTest(false);
9422                                 GL_DepthFunc(GL_EQUAL);
9423                         }
9424                 }
9425                 GL_DepthMask(layer->depthmask && writedepth);
9426                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9427                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9428                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9429                 switch (layer->type)
9430                 {
9431                 case TEXTURELAYERTYPE_LITTEXTURE:
9432                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9433                         {
9434                                 // two-pass lit texture with 2x rgbscale
9435                                 // first the lightmap pass
9436                                 R_Mesh_TexBind(0, r_texture_white);
9437                                 R_Mesh_TexMatrix(0, NULL);
9438                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9439                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9440                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9441                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9442                                 else if (FAKELIGHT_ENABLED)
9443                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9444                                 else if (rsurface.uselightmaptexture)
9445                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9446                                 else
9447                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9448                                 // then apply the texture to it
9449                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9450                                 R_Mesh_TexBind(0, layer->texture);
9451                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9452                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9453                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9454                                 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);
9455                         }
9456                         else
9457                         {
9458                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9459                                 R_Mesh_TexBind(0, layer->texture);
9460                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9461                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9462                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9463                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9464                                         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);
9465                                 else
9466                                         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);
9467                         }
9468                         break;
9469                 case TEXTURELAYERTYPE_TEXTURE:
9470                         // singletexture unlit texture with transparency support
9471                         R_Mesh_TexBind(0, layer->texture);
9472                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9473                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9474                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9475                         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);
9476                         break;
9477                 case TEXTURELAYERTYPE_FOG:
9478                         // singletexture fogging
9479                         if (layer->texture)
9480                         {
9481                                 R_Mesh_TexBind(0, layer->texture);
9482                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9483                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9484                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9485                         }
9486                         else
9487                         {
9488                                 R_Mesh_TexBind(0, 0);
9489                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9490                         }
9491                         // generate a color array for the fog pass
9492                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9493                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9494                         RSurf_DrawBatch();
9495                         break;
9496                 default:
9497                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9498                 }
9499         }
9500         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9501         {
9502                 GL_DepthFunc(GL_LEQUAL);
9503                 GL_AlphaTest(false);
9504         }
9505 }
9506
9507 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9508 {
9509         int vi;
9510         int j;
9511         r_vertexgeneric_t *batchvertex;
9512         float c[4];
9513
9514 //      R_Mesh_ResetTextureState();
9515         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9516
9517         if(rsurface.texture && rsurface.texture->currentskinframe)
9518         {
9519                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9520                 c[3] *= rsurface.texture->currentalpha;
9521         }
9522         else
9523         {
9524                 c[0] = 1;
9525                 c[1] = 0;
9526                 c[2] = 1;
9527                 c[3] = 1;
9528         }
9529
9530         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9531         {
9532                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9533                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9534                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9535         }
9536
9537         // brighten it up (as texture value 127 means "unlit")
9538         c[0] *= 2 * r_refdef.view.colorscale;
9539         c[1] *= 2 * r_refdef.view.colorscale;
9540         c[2] *= 2 * r_refdef.view.colorscale;
9541
9542         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9543                 c[3] *= r_wateralpha.value;
9544
9545         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9546         {
9547                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9548                 GL_DepthMask(false);
9549         }
9550         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9551         {
9552                 GL_BlendFunc(GL_ONE, GL_ONE);
9553                 GL_DepthMask(false);
9554         }
9555         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9556         {
9557                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9558                 GL_DepthMask(false);
9559         }
9560         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9561         {
9562                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9563                 GL_DepthMask(false);
9564         }
9565         else
9566         {
9567                 GL_BlendFunc(GL_ONE, GL_ZERO);
9568                 GL_DepthMask(writedepth);
9569         }
9570
9571         if (r_showsurfaces.integer == 3)
9572         {
9573                 rsurface.passcolor4f = NULL;
9574
9575                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9576                 {
9577                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9578
9579                         rsurface.passcolor4f = NULL;
9580                         rsurface.passcolor4f_vertexbuffer = 0;
9581                         rsurface.passcolor4f_bufferoffset = 0;
9582                 }
9583                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9584                 {
9585                         qboolean applycolor = true;
9586                         float one = 1.0;
9587
9588                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9589
9590                         r_refdef.lightmapintensity = 1;
9591                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9592                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9593                 }
9594                 else if (FAKELIGHT_ENABLED)
9595                 {
9596                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9597
9598                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9599                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9600                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9601                 }
9602                 else
9603                 {
9604                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9605
9606                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9607                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9608                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9609                 }
9610
9611                 if(!rsurface.passcolor4f)
9612                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9613
9614                 RSurf_DrawBatch_GL11_ApplyAmbient();
9615                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9616                 if(r_refdef.fogenabled)
9617                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9618                 RSurf_DrawBatch_GL11_ClampColor();
9619
9620                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9621                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9622                 RSurf_DrawBatch();
9623         }
9624         else if (!r_refdef.view.showdebug)
9625         {
9626                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9627                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9628                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9629                 {
9630                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9631                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9632                 }
9633                 R_Mesh_PrepareVertices_Generic_Unlock();
9634                 RSurf_DrawBatch();
9635         }
9636         else if (r_showsurfaces.integer == 4)
9637         {
9638                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9639                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9640                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9641                 {
9642                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9643                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9644                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9645                 }
9646                 R_Mesh_PrepareVertices_Generic_Unlock();
9647                 RSurf_DrawBatch();
9648         }
9649         else if (r_showsurfaces.integer == 2)
9650         {
9651                 const int *e;
9652                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9653                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9654                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9655                 {
9656                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9657                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9658                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9659                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9660                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9661                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9662                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9663                 }
9664                 R_Mesh_PrepareVertices_Generic_Unlock();
9665                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9666         }
9667         else
9668         {
9669                 int texturesurfaceindex;
9670                 int k;
9671                 const msurface_t *surface;
9672                 float surfacecolor4f[4];
9673                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9674                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9675                 vi = 0;
9676                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9677                 {
9678                         surface = texturesurfacelist[texturesurfaceindex];
9679                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9680                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9681                         for (j = 0;j < surface->num_vertices;j++)
9682                         {
9683                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9684                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9685                                 vi++;
9686                         }
9687                 }
9688                 R_Mesh_PrepareVertices_Generic_Unlock();
9689                 RSurf_DrawBatch();
9690         }
9691 }
9692
9693 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9694 {
9695         CHECKGLERROR
9696         RSurf_SetupDepthAndCulling();
9697         if (r_showsurfaces.integer)
9698         {
9699                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9700                 return;
9701         }
9702         switch (vid.renderpath)
9703         {
9704         case RENDERPATH_GL20:
9705         case RENDERPATH_D3D9:
9706         case RENDERPATH_D3D10:
9707         case RENDERPATH_D3D11:
9708         case RENDERPATH_SOFT:
9709         case RENDERPATH_GLES2:
9710                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9711                 break;
9712         case RENDERPATH_GL13:
9713                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9714                 break;
9715         case RENDERPATH_GL11:
9716                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9717                 break;
9718         }
9719         CHECKGLERROR
9720 }
9721
9722 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9723 {
9724         CHECKGLERROR
9725         RSurf_SetupDepthAndCulling();
9726         if (r_showsurfaces.integer)
9727         {
9728                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9729                 return;
9730         }
9731         switch (vid.renderpath)
9732         {
9733         case RENDERPATH_GL20:
9734         case RENDERPATH_D3D9:
9735         case RENDERPATH_D3D10:
9736         case RENDERPATH_D3D11:
9737         case RENDERPATH_SOFT:
9738         case RENDERPATH_GLES2:
9739                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9740                 break;
9741         case RENDERPATH_GL13:
9742                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9743                 break;
9744         case RENDERPATH_GL11:
9745                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9746                 break;
9747         }
9748         CHECKGLERROR
9749 }
9750
9751 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9752 {
9753         int i, j;
9754         int texturenumsurfaces, endsurface;
9755         texture_t *texture;
9756         const msurface_t *surface;
9757 #define MAXBATCH_TRANSPARENTSURFACES 256
9758         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9759
9760         // if the model is static it doesn't matter what value we give for
9761         // wantnormals and wanttangents, so this logic uses only rules applicable
9762         // to a model, knowing that they are meaningless otherwise
9763         if (ent == r_refdef.scene.worldentity)
9764                 RSurf_ActiveWorldEntity();
9765         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9766                 RSurf_ActiveModelEntity(ent, false, false, false);
9767         else
9768         {
9769                 switch (vid.renderpath)
9770                 {
9771                 case RENDERPATH_GL20:
9772                 case RENDERPATH_D3D9:
9773                 case RENDERPATH_D3D10:
9774                 case RENDERPATH_D3D11:
9775                 case RENDERPATH_SOFT:
9776                 case RENDERPATH_GLES2:
9777                         RSurf_ActiveModelEntity(ent, true, true, false);
9778                         break;
9779                 case RENDERPATH_GL13:
9780                 case RENDERPATH_GL11:
9781                         RSurf_ActiveModelEntity(ent, true, false, false);
9782                         break;
9783                 }
9784         }
9785
9786         if (r_transparentdepthmasking.integer)
9787         {
9788                 qboolean setup = false;
9789                 for (i = 0;i < numsurfaces;i = j)
9790                 {
9791                         j = i + 1;
9792                         surface = rsurface.modelsurfaces + surfacelist[i];
9793                         texture = surface->texture;
9794                         rsurface.texture = R_GetCurrentTexture(texture);
9795                         rsurface.lightmaptexture = NULL;
9796                         rsurface.deluxemaptexture = NULL;
9797                         rsurface.uselightmaptexture = false;
9798                         // scan ahead until we find a different texture
9799                         endsurface = min(i + 1024, numsurfaces);
9800                         texturenumsurfaces = 0;
9801                         texturesurfacelist[texturenumsurfaces++] = surface;
9802                         for (;j < endsurface;j++)
9803                         {
9804                                 surface = rsurface.modelsurfaces + surfacelist[j];
9805                                 if (texture != surface->texture)
9806                                         break;
9807                                 texturesurfacelist[texturenumsurfaces++] = surface;
9808                         }
9809                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9810                                 continue;
9811                         // render the range of surfaces as depth
9812                         if (!setup)
9813                         {
9814                                 setup = true;
9815                                 GL_ColorMask(0,0,0,0);
9816                                 GL_Color(1,1,1,1);
9817                                 GL_DepthTest(true);
9818                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9819                                 GL_DepthMask(true);
9820 //                              R_Mesh_ResetTextureState();
9821                                 R_SetupShader_DepthOrShadow();
9822                         }
9823                         RSurf_SetupDepthAndCulling();
9824                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9825                         if (rsurface.batchvertex3fbuffer)
9826                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9827                         else
9828                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9829                         RSurf_DrawBatch();
9830                 }
9831                 if (setup)
9832                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9833         }
9834
9835         for (i = 0;i < numsurfaces;i = j)
9836         {
9837                 j = i + 1;
9838                 surface = rsurface.modelsurfaces + surfacelist[i];
9839                 texture = surface->texture;
9840                 rsurface.texture = R_GetCurrentTexture(texture);
9841                 // scan ahead until we find a different texture
9842                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9843                 texturenumsurfaces = 0;
9844                 texturesurfacelist[texturenumsurfaces++] = surface;
9845                 if(FAKELIGHT_ENABLED)
9846                 {
9847                         rsurface.lightmaptexture = NULL;
9848                         rsurface.deluxemaptexture = NULL;
9849                         rsurface.uselightmaptexture = false;
9850                         for (;j < endsurface;j++)
9851                         {
9852                                 surface = rsurface.modelsurfaces + surfacelist[j];
9853                                 if (texture != surface->texture)
9854                                         break;
9855                                 texturesurfacelist[texturenumsurfaces++] = surface;
9856                         }
9857                 }
9858                 else
9859                 {
9860                         rsurface.lightmaptexture = surface->lightmaptexture;
9861                         rsurface.deluxemaptexture = surface->deluxemaptexture;
9862                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9863                         for (;j < endsurface;j++)
9864                         {
9865                                 surface = rsurface.modelsurfaces + surfacelist[j];
9866                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9867                                         break;
9868                                 texturesurfacelist[texturenumsurfaces++] = surface;
9869                         }
9870                 }
9871                 // render the range of surfaces
9872                 if (ent == r_refdef.scene.worldentity)
9873                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9874                 else
9875                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9876         }
9877         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9878 }
9879
9880 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9881 {
9882         // transparent surfaces get pushed off into the transparent queue
9883         int surfacelistindex;
9884         const msurface_t *surface;
9885         vec3_t tempcenter, center;
9886         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9887         {
9888                 surface = texturesurfacelist[surfacelistindex];
9889                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9890                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9891                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9892                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9893                 if (queueentity->transparent_offset) // transparent offset
9894                 {
9895                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9896                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9897                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9898                 }
9899                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9900         }
9901 }
9902
9903 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9904 {
9905         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9906                 return;
9907         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9908                 return;
9909         RSurf_SetupDepthAndCulling();
9910         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9911         if (rsurface.batchvertex3fbuffer)
9912                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9913         else
9914                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9915         RSurf_DrawBatch();
9916 }
9917
9918 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9919 {
9920         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9921         CHECKGLERROR
9922         if (depthonly)
9923                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9924         else if (prepass)
9925         {
9926                 if (!rsurface.texture->currentnumlayers)
9927                         return;
9928                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9929                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9930                 else
9931                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9932         }
9933         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9934                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9935         else if (!rsurface.texture->currentnumlayers)
9936                 return;
9937         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9938         {
9939                 // in the deferred case, transparent surfaces were queued during prepass
9940                 if (!r_shadow_usingdeferredprepass)
9941                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9942         }
9943         else
9944         {
9945                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9946                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9947         }
9948         CHECKGLERROR
9949 }
9950
9951 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9952 {
9953         int i, j;
9954         texture_t *texture;
9955         R_FrameData_SetMark();
9956         // break the surface list down into batches by texture and use of lightmapping
9957         for (i = 0;i < numsurfaces;i = j)
9958         {
9959                 j = i + 1;
9960                 // texture is the base texture pointer, rsurface.texture is the
9961                 // current frame/skin the texture is directing us to use (for example
9962                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9963                 // use skin 1 instead)
9964                 texture = surfacelist[i]->texture;
9965                 rsurface.texture = R_GetCurrentTexture(texture);
9966                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9967                 {
9968                         // if this texture is not the kind we want, skip ahead to the next one
9969                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9970                                 ;
9971                         continue;
9972                 }
9973                 if(FAKELIGHT_ENABLED || depthonly || prepass)
9974                 {
9975                         rsurface.lightmaptexture = NULL;
9976                         rsurface.deluxemaptexture = NULL;
9977                         rsurface.uselightmaptexture = false;
9978                         // simply scan ahead until we find a different texture or lightmap state
9979                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9980                                 ;
9981                 }
9982                 else
9983                 {
9984                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
9985                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
9986                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
9987                         // simply scan ahead until we find a different texture or lightmap state
9988                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
9989                                 ;
9990                 }
9991                 // render the range of surfaces
9992                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
9993         }
9994         R_FrameData_ReturnToMark();
9995 }
9996
9997 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
9998 {
9999         CHECKGLERROR
10000         if (depthonly)
10001                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10002         else if (prepass)
10003         {
10004                 if (!rsurface.texture->currentnumlayers)
10005                         return;
10006                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10007                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10008                 else
10009                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10010         }
10011         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10012                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10013         else if (!rsurface.texture->currentnumlayers)
10014                 return;
10015         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10016         {
10017                 // in the deferred case, transparent surfaces were queued during prepass
10018                 if (!r_shadow_usingdeferredprepass)
10019                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10020         }
10021         else
10022         {
10023                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10024                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10025         }
10026         CHECKGLERROR
10027 }
10028
10029 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10030 {
10031         int i, j;
10032         texture_t *texture;
10033         R_FrameData_SetMark();
10034         // break the surface list down into batches by texture and use of lightmapping
10035         for (i = 0;i < numsurfaces;i = j)
10036         {
10037                 j = i + 1;
10038                 // texture is the base texture pointer, rsurface.texture is the
10039                 // current frame/skin the texture is directing us to use (for example
10040                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10041                 // use skin 1 instead)
10042                 texture = surfacelist[i]->texture;
10043                 rsurface.texture = R_GetCurrentTexture(texture);
10044                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10045                 {
10046                         // if this texture is not the kind we want, skip ahead to the next one
10047                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10048                                 ;
10049                         continue;
10050                 }
10051                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10052                 {
10053                         rsurface.lightmaptexture = NULL;
10054                         rsurface.deluxemaptexture = NULL;
10055                         rsurface.uselightmaptexture = false;
10056                         // simply scan ahead until we find a different texture or lightmap state
10057                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10058                                 ;
10059                 }
10060                 else
10061                 {
10062                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10063                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10064                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10065                         // simply scan ahead until we find a different texture or lightmap state
10066                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10067                                 ;
10068                 }
10069                 // render the range of surfaces
10070                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10071         }
10072         R_FrameData_ReturnToMark();
10073 }
10074
10075 float locboxvertex3f[6*4*3] =
10076 {
10077         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10078         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10079         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10080         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10081         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10082         1,0,0, 0,0,0, 0,1,0, 1,1,0
10083 };
10084
10085 unsigned short locboxelements[6*2*3] =
10086 {
10087          0, 1, 2, 0, 2, 3,
10088          4, 5, 6, 4, 6, 7,
10089          8, 9,10, 8,10,11,
10090         12,13,14, 12,14,15,
10091         16,17,18, 16,18,19,
10092         20,21,22, 20,22,23
10093 };
10094
10095 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10096 {
10097         int i, j;
10098         cl_locnode_t *loc = (cl_locnode_t *)ent;
10099         vec3_t mins, size;
10100         float vertex3f[6*4*3];
10101         CHECKGLERROR
10102         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10103         GL_DepthMask(false);
10104         GL_DepthRange(0, 1);
10105         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10106         GL_DepthTest(true);
10107         GL_CullFace(GL_NONE);
10108         R_EntityMatrix(&identitymatrix);
10109
10110 //      R_Mesh_ResetTextureState();
10111
10112         i = surfacelist[0];
10113         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10114                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10115                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10116                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10117
10118         if (VectorCompare(loc->mins, loc->maxs))
10119         {
10120                 VectorSet(size, 2, 2, 2);
10121                 VectorMA(loc->mins, -0.5f, size, mins);
10122         }
10123         else
10124         {
10125                 VectorCopy(loc->mins, mins);
10126                 VectorSubtract(loc->maxs, loc->mins, size);
10127         }
10128
10129         for (i = 0;i < 6*4*3;)
10130                 for (j = 0;j < 3;j++, i++)
10131                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10132
10133         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10134         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10135         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10136 }
10137
10138 void R_DrawLocs(void)
10139 {
10140         int index;
10141         cl_locnode_t *loc, *nearestloc;
10142         vec3_t center;
10143         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10144         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10145         {
10146                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10147                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10148         }
10149 }
10150
10151 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10152 {
10153         if (decalsystem->decals)
10154                 Mem_Free(decalsystem->decals);
10155         memset(decalsystem, 0, sizeof(*decalsystem));
10156 }
10157
10158 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)
10159 {
10160         tridecal_t *decal;
10161         tridecal_t *decals;
10162         int i;
10163
10164         // expand or initialize the system
10165         if (decalsystem->maxdecals <= decalsystem->numdecals)
10166         {
10167                 decalsystem_t old = *decalsystem;
10168                 qboolean useshortelements;
10169                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10170                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10171                 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)));
10172                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10173                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10174                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10175                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10176                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10177                 if (decalsystem->numdecals)
10178                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10179                 if (old.decals)
10180                         Mem_Free(old.decals);
10181                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10182                         decalsystem->element3i[i] = i;
10183                 if (useshortelements)
10184                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10185                                 decalsystem->element3s[i] = i;
10186         }
10187
10188         // grab a decal and search for another free slot for the next one
10189         decals = decalsystem->decals;
10190         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10191         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10192                 ;
10193         decalsystem->freedecal = i;
10194         if (decalsystem->numdecals <= i)
10195                 decalsystem->numdecals = i + 1;
10196
10197         // initialize the decal
10198         decal->lived = 0;
10199         decal->triangleindex = triangleindex;
10200         decal->surfaceindex = surfaceindex;
10201         decal->decalsequence = decalsequence;
10202         decal->color4f[0][0] = c0[0];
10203         decal->color4f[0][1] = c0[1];
10204         decal->color4f[0][2] = c0[2];
10205         decal->color4f[0][3] = 1;
10206         decal->color4f[1][0] = c1[0];
10207         decal->color4f[1][1] = c1[1];
10208         decal->color4f[1][2] = c1[2];
10209         decal->color4f[1][3] = 1;
10210         decal->color4f[2][0] = c2[0];
10211         decal->color4f[2][1] = c2[1];
10212         decal->color4f[2][2] = c2[2];
10213         decal->color4f[2][3] = 1;
10214         decal->vertex3f[0][0] = v0[0];
10215         decal->vertex3f[0][1] = v0[1];
10216         decal->vertex3f[0][2] = v0[2];
10217         decal->vertex3f[1][0] = v1[0];
10218         decal->vertex3f[1][1] = v1[1];
10219         decal->vertex3f[1][2] = v1[2];
10220         decal->vertex3f[2][0] = v2[0];
10221         decal->vertex3f[2][1] = v2[1];
10222         decal->vertex3f[2][2] = v2[2];
10223         decal->texcoord2f[0][0] = t0[0];
10224         decal->texcoord2f[0][1] = t0[1];
10225         decal->texcoord2f[1][0] = t1[0];
10226         decal->texcoord2f[1][1] = t1[1];
10227         decal->texcoord2f[2][0] = t2[0];
10228         decal->texcoord2f[2][1] = t2[1];
10229 }
10230
10231 extern cvar_t cl_decals_bias;
10232 extern cvar_t cl_decals_models;
10233 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10234 // baseparms, parms, temps
10235 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)
10236 {
10237         int cornerindex;
10238         int index;
10239         float v[9][3];
10240         const float *vertex3f;
10241         const float *normal3f;
10242         int numpoints;
10243         float points[2][9][3];
10244         float temp[3];
10245         float tc[9][2];
10246         float f;
10247         float c[9][4];
10248         const int *e;
10249
10250         e = rsurface.modelelement3i + 3*triangleindex;
10251
10252         vertex3f = rsurface.modelvertex3f;
10253         normal3f = rsurface.modelnormal3f;
10254
10255         for (cornerindex = 0;cornerindex < 3;cornerindex++)
10256         {
10257                 index = 3*e[cornerindex];
10258                 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10259         }
10260         // cull backfaces
10261         //TriangleNormal(v[0], v[1], v[2], normal);
10262         //if (DotProduct(normal, localnormal) < 0.0f)
10263         //      continue;
10264         // clip by each of the box planes formed from the projection matrix
10265         // if anything survives, we emit the decal
10266         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]);
10267         if (numpoints < 3)
10268                 return;
10269         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]);
10270         if (numpoints < 3)
10271                 return;
10272         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]);
10273         if (numpoints < 3)
10274                 return;
10275         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]);
10276         if (numpoints < 3)
10277                 return;
10278         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]);
10279         if (numpoints < 3)
10280                 return;
10281         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]);
10282         if (numpoints < 3)
10283                 return;
10284         // some part of the triangle survived, so we have to accept it...
10285         if (dynamic)
10286         {
10287                 // dynamic always uses the original triangle
10288                 numpoints = 3;
10289                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10290                 {
10291                         index = 3*e[cornerindex];
10292                         VectorCopy(vertex3f + index, v[cornerindex]);
10293                 }
10294         }
10295         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10296         {
10297                 // convert vertex positions to texcoords
10298                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10299                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10300                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10301                 // calculate distance fade from the projection origin
10302                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10303                 f = bound(0.0f, f, 1.0f);
10304                 c[cornerindex][0] = r * f;
10305                 c[cornerindex][1] = g * f;
10306                 c[cornerindex][2] = b * f;
10307                 c[cornerindex][3] = 1.0f;
10308                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10309         }
10310         if (dynamic)
10311                 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);
10312         else
10313                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10314                         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);
10315 }
10316 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)
10317 {
10318         matrix4x4_t projection;
10319         decalsystem_t *decalsystem;
10320         qboolean dynamic;
10321         dp_model_t *model;
10322         const msurface_t *surface;
10323         const msurface_t *surfaces;
10324         const int *surfacelist;
10325         const texture_t *texture;
10326         int numtriangles;
10327         int numsurfacelist;
10328         int surfacelistindex;
10329         int surfaceindex;
10330         int triangleindex;
10331         float localorigin[3];
10332         float localnormal[3];
10333         float localmins[3];
10334         float localmaxs[3];
10335         float localsize;
10336         //float normal[3];
10337         float planes[6][4];
10338         float angles[3];
10339         bih_t *bih;
10340         int bih_triangles_count;
10341         int bih_triangles[256];
10342         int bih_surfaces[256];
10343
10344         decalsystem = &ent->decalsystem;
10345         model = ent->model;
10346         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10347         {
10348                 R_DecalSystem_Reset(&ent->decalsystem);
10349                 return;
10350         }
10351
10352         if (!model->brush.data_leafs && !cl_decals_models.integer)
10353         {
10354                 if (decalsystem->model)
10355                         R_DecalSystem_Reset(decalsystem);
10356                 return;
10357         }
10358
10359         if (decalsystem->model != model)
10360                 R_DecalSystem_Reset(decalsystem);
10361         decalsystem->model = model;
10362
10363         RSurf_ActiveModelEntity(ent, true, false, false);
10364
10365         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10366         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10367         VectorNormalize(localnormal);
10368         localsize = worldsize*rsurface.inversematrixscale;
10369         localmins[0] = localorigin[0] - localsize;
10370         localmins[1] = localorigin[1] - localsize;
10371         localmins[2] = localorigin[2] - localsize;
10372         localmaxs[0] = localorigin[0] + localsize;
10373         localmaxs[1] = localorigin[1] + localsize;
10374         localmaxs[2] = localorigin[2] + localsize;
10375
10376         //VectorCopy(localnormal, planes[4]);
10377         //VectorVectors(planes[4], planes[2], planes[0]);
10378         AnglesFromVectors(angles, localnormal, NULL, false);
10379         AngleVectors(angles, planes[0], planes[2], planes[4]);
10380         VectorNegate(planes[0], planes[1]);
10381         VectorNegate(planes[2], planes[3]);
10382         VectorNegate(planes[4], planes[5]);
10383         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10384         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10385         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10386         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10387         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10388         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10389
10390 #if 1
10391 // works
10392 {
10393         matrix4x4_t forwardprojection;
10394         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10395         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10396 }
10397 #else
10398 // broken
10399 {
10400         float projectionvector[4][3];
10401         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10402         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10403         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10404         projectionvector[0][0] = planes[0][0] * ilocalsize;
10405         projectionvector[0][1] = planes[1][0] * ilocalsize;
10406         projectionvector[0][2] = planes[2][0] * ilocalsize;
10407         projectionvector[1][0] = planes[0][1] * ilocalsize;
10408         projectionvector[1][1] = planes[1][1] * ilocalsize;
10409         projectionvector[1][2] = planes[2][1] * ilocalsize;
10410         projectionvector[2][0] = planes[0][2] * ilocalsize;
10411         projectionvector[2][1] = planes[1][2] * ilocalsize;
10412         projectionvector[2][2] = planes[2][2] * ilocalsize;
10413         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10414         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10415         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10416         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10417 }
10418 #endif
10419
10420         dynamic = model->surfmesh.isanimated;
10421         numsurfacelist = model->nummodelsurfaces;
10422         surfacelist = model->sortedmodelsurfaces;
10423         surfaces = model->data_surfaces;
10424
10425         bih = NULL;
10426         bih_triangles_count = -1;
10427         if(!dynamic)
10428         {
10429                 if(model->render_bih.numleafs)
10430                         bih = &model->render_bih;
10431                 else if(model->collision_bih.numleafs)
10432                         bih = &model->collision_bih;
10433         }
10434         if(bih)
10435                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10436         if(bih_triangles_count == 0)
10437                 return;
10438         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10439                 return;
10440         if(bih_triangles_count > 0)
10441         {
10442                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10443                 {
10444                         surfaceindex = bih_surfaces[triangleindex];
10445                         surface = surfaces + surfaceindex;
10446                         texture = surface->texture;
10447                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10448                                 continue;
10449                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10450                                 continue;
10451                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10452                 }
10453         }
10454         else
10455         {
10456                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10457                 {
10458                         surfaceindex = surfacelist[surfacelistindex];
10459                         surface = surfaces + surfaceindex;
10460                         // check cull box first because it rejects more than any other check
10461                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10462                                 continue;
10463                         // skip transparent surfaces
10464                         texture = surface->texture;
10465                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10466                                 continue;
10467                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10468                                 continue;
10469                         numtriangles = surface->num_triangles;
10470                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10471                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10472                 }
10473         }
10474 }
10475
10476 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10477 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)
10478 {
10479         int renderentityindex;
10480         float worldmins[3];
10481         float worldmaxs[3];
10482         entity_render_t *ent;
10483
10484         if (!cl_decals_newsystem.integer)
10485                 return;
10486
10487         worldmins[0] = worldorigin[0] - worldsize;
10488         worldmins[1] = worldorigin[1] - worldsize;
10489         worldmins[2] = worldorigin[2] - worldsize;
10490         worldmaxs[0] = worldorigin[0] + worldsize;
10491         worldmaxs[1] = worldorigin[1] + worldsize;
10492         worldmaxs[2] = worldorigin[2] + worldsize;
10493
10494         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10495
10496         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10497         {
10498                 ent = r_refdef.scene.entities[renderentityindex];
10499                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10500                         continue;
10501
10502                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10503         }
10504 }
10505
10506 typedef struct r_decalsystem_splatqueue_s
10507 {
10508         vec3_t worldorigin;
10509         vec3_t worldnormal;
10510         float color[4];
10511         float tcrange[4];
10512         float worldsize;
10513         int decalsequence;
10514 }
10515 r_decalsystem_splatqueue_t;
10516
10517 int r_decalsystem_numqueued = 0;
10518 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10519
10520 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)
10521 {
10522         r_decalsystem_splatqueue_t *queue;
10523
10524         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10525                 return;
10526
10527         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10528         VectorCopy(worldorigin, queue->worldorigin);
10529         VectorCopy(worldnormal, queue->worldnormal);
10530         Vector4Set(queue->color, r, g, b, a);
10531         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10532         queue->worldsize = worldsize;
10533         queue->decalsequence = cl.decalsequence++;
10534 }
10535
10536 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10537 {
10538         int i;
10539         r_decalsystem_splatqueue_t *queue;
10540
10541         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10542                 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);
10543         r_decalsystem_numqueued = 0;
10544 }
10545
10546 extern cvar_t cl_decals_max;
10547 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10548 {
10549         int i;
10550         decalsystem_t *decalsystem = &ent->decalsystem;
10551         int numdecals;
10552         int killsequence;
10553         tridecal_t *decal;
10554         float frametime;
10555         float lifetime;
10556
10557         if (!decalsystem->numdecals)
10558                 return;
10559
10560         if (r_showsurfaces.integer)
10561                 return;
10562
10563         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10564         {
10565                 R_DecalSystem_Reset(decalsystem);
10566                 return;
10567         }
10568
10569         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10570         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10571
10572         if (decalsystem->lastupdatetime)
10573                 frametime = (cl.time - decalsystem->lastupdatetime);
10574         else
10575                 frametime = 0;
10576         decalsystem->lastupdatetime = cl.time;
10577         decal = decalsystem->decals;
10578         numdecals = decalsystem->numdecals;
10579
10580         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10581         {
10582                 if (decal->color4f[0][3])
10583                 {
10584                         decal->lived += frametime;
10585                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10586                         {
10587                                 memset(decal, 0, sizeof(*decal));
10588                                 if (decalsystem->freedecal > i)
10589                                         decalsystem->freedecal = i;
10590                         }
10591                 }
10592         }
10593         decal = decalsystem->decals;
10594         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10595                 numdecals--;
10596
10597         // collapse the array by shuffling the tail decals into the gaps
10598         for (;;)
10599         {
10600                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10601                         decalsystem->freedecal++;
10602                 if (decalsystem->freedecal == numdecals)
10603                         break;
10604                 decal[decalsystem->freedecal] = decal[--numdecals];
10605         }
10606
10607         decalsystem->numdecals = numdecals;
10608
10609         if (numdecals <= 0)
10610         {
10611                 // if there are no decals left, reset decalsystem
10612                 R_DecalSystem_Reset(decalsystem);
10613         }
10614 }
10615
10616 extern skinframe_t *decalskinframe;
10617 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10618 {
10619         int i;
10620         decalsystem_t *decalsystem = &ent->decalsystem;
10621         int numdecals;
10622         tridecal_t *decal;
10623         float faderate;
10624         float alpha;
10625         float *v3f;
10626         float *c4f;
10627         float *t2f;
10628         const int *e;
10629         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10630         int numtris = 0;
10631
10632         numdecals = decalsystem->numdecals;
10633         if (!numdecals)
10634                 return;
10635
10636         if (r_showsurfaces.integer)
10637                 return;
10638
10639         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10640         {
10641                 R_DecalSystem_Reset(decalsystem);
10642                 return;
10643         }
10644
10645         // if the model is static it doesn't matter what value we give for
10646         // wantnormals and wanttangents, so this logic uses only rules applicable
10647         // to a model, knowing that they are meaningless otherwise
10648         if (ent == r_refdef.scene.worldentity)
10649                 RSurf_ActiveWorldEntity();
10650         else
10651                 RSurf_ActiveModelEntity(ent, false, false, false);
10652
10653         decalsystem->lastupdatetime = cl.time;
10654         decal = decalsystem->decals;
10655
10656         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10657
10658         // update vertex positions for animated models
10659         v3f = decalsystem->vertex3f;
10660         c4f = decalsystem->color4f;
10661         t2f = decalsystem->texcoord2f;
10662         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10663         {
10664                 if (!decal->color4f[0][3])
10665                         continue;
10666
10667                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10668                         continue;
10669
10670                 // update color values for fading decals
10671                 if (decal->lived >= cl_decals_time.value)
10672                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10673                 else
10674                         alpha = 1.0f;
10675
10676                 c4f[ 0] = decal->color4f[0][0] * alpha;
10677                 c4f[ 1] = decal->color4f[0][1] * alpha;
10678                 c4f[ 2] = decal->color4f[0][2] * alpha;
10679                 c4f[ 3] = 1;
10680                 c4f[ 4] = decal->color4f[1][0] * alpha;
10681                 c4f[ 5] = decal->color4f[1][1] * alpha;
10682                 c4f[ 6] = decal->color4f[1][2] * alpha;
10683                 c4f[ 7] = 1;
10684                 c4f[ 8] = decal->color4f[2][0] * alpha;
10685                 c4f[ 9] = decal->color4f[2][1] * alpha;
10686                 c4f[10] = decal->color4f[2][2] * alpha;
10687                 c4f[11] = 1;
10688
10689                 t2f[0] = decal->texcoord2f[0][0];
10690                 t2f[1] = decal->texcoord2f[0][1];
10691                 t2f[2] = decal->texcoord2f[1][0];
10692                 t2f[3] = decal->texcoord2f[1][1];
10693                 t2f[4] = decal->texcoord2f[2][0];
10694                 t2f[5] = decal->texcoord2f[2][1];
10695
10696                 // update vertex positions for animated models
10697                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10698                 {
10699                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10700                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10701                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10702                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10703                 }
10704                 else
10705                 {
10706                         VectorCopy(decal->vertex3f[0], v3f);
10707                         VectorCopy(decal->vertex3f[1], v3f + 3);
10708                         VectorCopy(decal->vertex3f[2], v3f + 6);
10709                 }
10710
10711                 if (r_refdef.fogenabled)
10712                 {
10713                         alpha = RSurf_FogVertex(v3f);
10714                         VectorScale(c4f, alpha, c4f);
10715                         alpha = RSurf_FogVertex(v3f + 3);
10716                         VectorScale(c4f + 4, alpha, c4f + 4);
10717                         alpha = RSurf_FogVertex(v3f + 6);
10718                         VectorScale(c4f + 8, alpha, c4f + 8);
10719                 }
10720
10721                 v3f += 9;
10722                 c4f += 12;
10723                 t2f += 6;
10724                 numtris++;
10725         }
10726
10727         if (numtris > 0)
10728         {
10729                 r_refdef.stats.drawndecals += numtris;
10730
10731                 // now render the decals all at once
10732                 // (this assumes they all use one particle font texture!)
10733                 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);
10734 //              R_Mesh_ResetTextureState();
10735                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10736                 GL_DepthMask(false);
10737                 GL_DepthRange(0, 1);
10738                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10739                 GL_DepthTest(true);
10740                 GL_CullFace(GL_NONE);
10741                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10742                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10743                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10744         }
10745 }
10746
10747 static void R_DrawModelDecals(void)
10748 {
10749         int i, numdecals;
10750
10751         // fade faster when there are too many decals
10752         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10753         for (i = 0;i < r_refdef.scene.numentities;i++)
10754                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10755
10756         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10757         for (i = 0;i < r_refdef.scene.numentities;i++)
10758                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10759                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10760
10761         R_DecalSystem_ApplySplatEntitiesQueue();
10762
10763         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10764         for (i = 0;i < r_refdef.scene.numentities;i++)
10765                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10766
10767         r_refdef.stats.totaldecals += numdecals;
10768
10769         if (r_showsurfaces.integer)
10770                 return;
10771
10772         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10773
10774         for (i = 0;i < r_refdef.scene.numentities;i++)
10775         {
10776                 if (!r_refdef.viewcache.entityvisible[i])
10777                         continue;
10778                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10779                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10780         }
10781 }
10782
10783 extern cvar_t mod_collision_bih;
10784 void R_DrawDebugModel(void)
10785 {
10786         entity_render_t *ent = rsurface.entity;
10787         int i, j, k, l, flagsmask;
10788         const msurface_t *surface;
10789         dp_model_t *model = ent->model;
10790         vec3_t v;
10791
10792         switch(vid.renderpath)
10793         {
10794         case RENDERPATH_GL11:
10795         case RENDERPATH_GL13:
10796         case RENDERPATH_GL20:
10797                 break;
10798         case RENDERPATH_D3D9:
10799                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10800                 return;
10801         case RENDERPATH_D3D10:
10802                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10803                 return;
10804         case RENDERPATH_D3D11:
10805                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10806                 return;
10807         case RENDERPATH_SOFT:
10808                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10809                 return;
10810         case RENDERPATH_GLES2:
10811                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10812                 return;
10813         }
10814
10815         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10816
10817 //      R_Mesh_ResetTextureState();
10818         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10819         GL_DepthRange(0, 1);
10820         GL_DepthTest(!r_showdisabledepthtest.integer);
10821         GL_DepthMask(false);
10822         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10823
10824         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10825         {
10826                 int triangleindex;
10827                 int bihleafindex;
10828                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10829                 const q3mbrush_t *brush;
10830                 const bih_t *bih = &model->collision_bih;
10831                 const bih_leaf_t *bihleaf;
10832                 float vertex3f[3][3];
10833                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10834                 cullbox = false;
10835                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10836                 {
10837                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10838                                 continue;
10839                         switch (bihleaf->type)
10840                         {
10841                         case BIH_BRUSH:
10842                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10843                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10844                                 {
10845                                         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);
10846                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10847                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10848                                 }
10849                                 break;
10850                         case BIH_COLLISIONTRIANGLE:
10851                                 triangleindex = bihleaf->itemindex;
10852                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10853                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10854                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10855                                 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);
10856                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10857                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10858                                 break;
10859                         case BIH_RENDERTRIANGLE:
10860                                 triangleindex = bihleaf->itemindex;
10861                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10862                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10863                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10864                                 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);
10865                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10866                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10867                                 break;
10868                         }
10869                 }
10870         }
10871
10872         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10873
10874         if (r_showtris.integer || (r_shownormals.value != 0))
10875         {
10876                 if (r_showdisabledepthtest.integer)
10877                 {
10878                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10879                         GL_DepthMask(false);
10880                 }
10881                 else
10882                 {
10883                         GL_BlendFunc(GL_ONE, GL_ZERO);
10884                         GL_DepthMask(true);
10885                 }
10886                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10887                 {
10888                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10889                                 continue;
10890                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10891                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10892                         {
10893                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10894                                 if (r_showtris.value > 0)
10895                                 {
10896                                         if (!rsurface.texture->currentlayers->depthmask)
10897                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10898                                         else if (ent == r_refdef.scene.worldentity)
10899                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10900                                         else
10901                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10902                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10903                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10904                                         RSurf_DrawBatch();
10905                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10906                                         CHECKGLERROR
10907                                 }
10908                                 if (r_shownormals.value < 0)
10909                                 {
10910                                         qglBegin(GL_LINES);
10911                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10912                                         {
10913                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10914                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10915                                                 qglVertex3f(v[0], v[1], v[2]);
10916                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10917                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10918                                                 qglVertex3f(v[0], v[1], v[2]);
10919                                         }
10920                                         qglEnd();
10921                                         CHECKGLERROR
10922                                 }
10923                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10924                                 {
10925                                         qglBegin(GL_LINES);
10926                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10927                                         {
10928                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10929                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10930                                                 qglVertex3f(v[0], v[1], v[2]);
10931                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10932                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10933                                                 qglVertex3f(v[0], v[1], v[2]);
10934                                         }
10935                                         qglEnd();
10936                                         CHECKGLERROR
10937                                         qglBegin(GL_LINES);
10938                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10939                                         {
10940                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10941                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10942                                                 qglVertex3f(v[0], v[1], v[2]);
10943                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10944                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10945                                                 qglVertex3f(v[0], v[1], v[2]);
10946                                         }
10947                                         qglEnd();
10948                                         CHECKGLERROR
10949                                         qglBegin(GL_LINES);
10950                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10951                                         {
10952                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10953                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10954                                                 qglVertex3f(v[0], v[1], v[2]);
10955                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10956                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10957                                                 qglVertex3f(v[0], v[1], v[2]);
10958                                         }
10959                                         qglEnd();
10960                                         CHECKGLERROR
10961                                 }
10962                         }
10963                 }
10964                 rsurface.texture = NULL;
10965         }
10966 }
10967
10968 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10969 int r_maxsurfacelist = 0;
10970 const msurface_t **r_surfacelist = NULL;
10971 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10972 {
10973         int i, j, endj, flagsmask;
10974         dp_model_t *model = r_refdef.scene.worldmodel;
10975         msurface_t *surfaces;
10976         unsigned char *update;
10977         int numsurfacelist = 0;
10978         if (model == NULL)
10979                 return;
10980
10981         if (r_maxsurfacelist < model->num_surfaces)
10982         {
10983                 r_maxsurfacelist = model->num_surfaces;
10984                 if (r_surfacelist)
10985                         Mem_Free((msurface_t**)r_surfacelist);
10986                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10987         }
10988
10989         RSurf_ActiveWorldEntity();
10990
10991         surfaces = model->data_surfaces;
10992         update = model->brushq1.lightmapupdateflags;
10993
10994         // update light styles on this submodel
10995         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
10996         {
10997                 model_brush_lightstyleinfo_t *style;
10998                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
10999                 {
11000                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11001                         {
11002                                 int *list = style->surfacelist;
11003                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11004                                 for (j = 0;j < style->numsurfaces;j++)
11005                                         update[list[j]] = true;
11006                         }
11007                 }
11008         }
11009
11010         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11011
11012         if (debug)
11013         {
11014                 R_DrawDebugModel();
11015                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11016                 return;
11017         }
11018
11019         rsurface.lightmaptexture = NULL;
11020         rsurface.deluxemaptexture = NULL;
11021         rsurface.uselightmaptexture = false;
11022         rsurface.texture = NULL;
11023         rsurface.rtlight = NULL;
11024         numsurfacelist = 0;
11025         // add visible surfaces to draw list
11026         for (i = 0;i < model->nummodelsurfaces;i++)
11027         {
11028                 j = model->sortedmodelsurfaces[i];
11029                 if (r_refdef.viewcache.world_surfacevisible[j])
11030                         r_surfacelist[numsurfacelist++] = surfaces + j;
11031         }
11032         // update lightmaps if needed
11033         if (model->brushq1.firstrender)
11034         {
11035                 model->brushq1.firstrender = false;
11036                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11037                         if (update[j])
11038                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11039         }
11040         else if (update)
11041         {
11042                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11043                         if (r_refdef.viewcache.world_surfacevisible[j])
11044                                 if (update[j])
11045                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11046         }
11047         // don't do anything if there were no surfaces
11048         if (!numsurfacelist)
11049         {
11050                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11051                 return;
11052         }
11053         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11054
11055         // add to stats if desired
11056         if (r_speeds.integer && !skysurfaces && !depthonly)
11057         {
11058                 r_refdef.stats.world_surfaces += numsurfacelist;
11059                 for (j = 0;j < numsurfacelist;j++)
11060                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11061         }
11062
11063         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11064 }
11065
11066 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11067 {
11068         int i, j, endj, flagsmask;
11069         dp_model_t *model = ent->model;
11070         msurface_t *surfaces;
11071         unsigned char *update;
11072         int numsurfacelist = 0;
11073         if (model == NULL)
11074                 return;
11075
11076         if (r_maxsurfacelist < model->num_surfaces)
11077         {
11078                 r_maxsurfacelist = model->num_surfaces;
11079                 if (r_surfacelist)
11080                         Mem_Free((msurface_t **)r_surfacelist);
11081                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11082         }
11083
11084         // if the model is static it doesn't matter what value we give for
11085         // wantnormals and wanttangents, so this logic uses only rules applicable
11086         // to a model, knowing that they are meaningless otherwise
11087         if (ent == r_refdef.scene.worldentity)
11088                 RSurf_ActiveWorldEntity();
11089         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11090                 RSurf_ActiveModelEntity(ent, false, false, false);
11091         else if (prepass)
11092                 RSurf_ActiveModelEntity(ent, true, true, true);
11093         else if (depthonly)
11094         {
11095                 switch (vid.renderpath)
11096                 {
11097                 case RENDERPATH_GL20:
11098                 case RENDERPATH_D3D9:
11099                 case RENDERPATH_D3D10:
11100                 case RENDERPATH_D3D11:
11101                 case RENDERPATH_SOFT:
11102                 case RENDERPATH_GLES2:
11103                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11104                         break;
11105                 case RENDERPATH_GL13:
11106                 case RENDERPATH_GL11:
11107                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11108                         break;
11109                 }
11110         }
11111         else
11112         {
11113                 switch (vid.renderpath)
11114                 {
11115                 case RENDERPATH_GL20:
11116                 case RENDERPATH_D3D9:
11117                 case RENDERPATH_D3D10:
11118                 case RENDERPATH_D3D11:
11119                 case RENDERPATH_SOFT:
11120                 case RENDERPATH_GLES2:
11121                         RSurf_ActiveModelEntity(ent, true, true, false);
11122                         break;
11123                 case RENDERPATH_GL13:
11124                 case RENDERPATH_GL11:
11125                         RSurf_ActiveModelEntity(ent, true, false, false);
11126                         break;
11127                 }
11128         }
11129
11130         surfaces = model->data_surfaces;
11131         update = model->brushq1.lightmapupdateflags;
11132
11133         // update light styles
11134         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11135         {
11136                 model_brush_lightstyleinfo_t *style;
11137                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11138                 {
11139                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11140                         {
11141                                 int *list = style->surfacelist;
11142                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11143                                 for (j = 0;j < style->numsurfaces;j++)
11144                                         update[list[j]] = true;
11145                         }
11146                 }
11147         }
11148
11149         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11150
11151         if (debug)
11152         {
11153                 R_DrawDebugModel();
11154                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11155                 return;
11156         }
11157
11158         rsurface.lightmaptexture = NULL;
11159         rsurface.deluxemaptexture = NULL;
11160         rsurface.uselightmaptexture = false;
11161         rsurface.texture = NULL;
11162         rsurface.rtlight = NULL;
11163         numsurfacelist = 0;
11164         // add visible surfaces to draw list
11165         for (i = 0;i < model->nummodelsurfaces;i++)
11166                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11167         // don't do anything if there were no surfaces
11168         if (!numsurfacelist)
11169         {
11170                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11171                 return;
11172         }
11173         // update lightmaps if needed
11174         if (update)
11175         {
11176                 int updated = 0;
11177                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11178                 {
11179                         if (update[j])
11180                         {
11181                                 updated++;
11182                                 R_BuildLightMap(ent, surfaces + j);
11183                         }
11184                 }
11185         }
11186         if (update)
11187                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11188                         if (update[j])
11189                                 R_BuildLightMap(ent, surfaces + j);
11190         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11191
11192         // add to stats if desired
11193         if (r_speeds.integer && !skysurfaces && !depthonly)
11194         {
11195                 r_refdef.stats.entities_surfaces += numsurfacelist;
11196                 for (j = 0;j < numsurfacelist;j++)
11197                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11198         }
11199
11200         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11201 }
11202
11203 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11204 {
11205         static texture_t texture;
11206         static msurface_t surface;
11207         const msurface_t *surfacelist = &surface;
11208
11209         // fake enough texture and surface state to render this geometry
11210
11211         texture.update_lastrenderframe = -1; // regenerate this texture
11212         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11213         texture.currentskinframe = skinframe;
11214         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11215         texture.offsetmapping = OFFSETMAPPING_OFF;
11216         texture.offsetscale = 1;
11217         texture.specularscalemod = 1;
11218         texture.specularpowermod = 1;
11219
11220         surface.texture = &texture;
11221         surface.num_triangles = numtriangles;
11222         surface.num_firsttriangle = firsttriangle;
11223         surface.num_vertices = numvertices;
11224         surface.num_firstvertex = firstvertex;
11225
11226         // now render it
11227         rsurface.texture = R_GetCurrentTexture(surface.texture);
11228         rsurface.lightmaptexture = NULL;
11229         rsurface.deluxemaptexture = NULL;
11230         rsurface.uselightmaptexture = false;
11231         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11232 }
11233
11234 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)
11235 {
11236         static msurface_t surface;
11237         const msurface_t *surfacelist = &surface;
11238
11239         // fake enough texture and surface state to render this geometry
11240         surface.texture = texture;
11241         surface.num_triangles = numtriangles;
11242         surface.num_firsttriangle = firsttriangle;
11243         surface.num_vertices = numvertices;
11244         surface.num_firstvertex = firstvertex;
11245
11246         // now render it
11247         rsurface.texture = R_GetCurrentTexture(surface.texture);
11248         rsurface.lightmaptexture = NULL;
11249         rsurface.deluxemaptexture = NULL;
11250         rsurface.uselightmaptexture = false;
11251         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11252 }