]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
790dbca4ad9457461078fbeb72658556c3836c50
[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 USEFOGALPHAHACK\n", " fogalphahack"},
637         {"#define USEGAMMARAMPS\n", " gammaramps"},
638         {"#define USECUBEFILTER\n", " cubefilter"},
639         {"#define USEGLOW\n", " glow"},
640         {"#define USEBLOOM\n", " bloom"},
641         {"#define USESPECULAR\n", " specular"},
642         {"#define USEPOSTPROCESSING\n", " postprocessing"},
643         {"#define USEREFLECTION\n", " reflection"},
644         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
645         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
646         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
647         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
648         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
649         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
650         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
651         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
652         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
653         {"#define USEALPHAKILL\n", " alphakill"},
654         {"#define USEREFLECTCUBE\n", " reflectcube"},
655         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
656         {"#define USEBOUNCEGRID\n", " bouncegrid"},
657 };
658
659 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
660 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
661 {
662         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
663         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
664         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
678 };
679
680 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
681 {
682         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
683         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
698 };
699
700 struct r_glsl_permutation_s;
701 typedef struct r_glsl_permutation_s
702 {
703         /// hash lookup data
704         struct r_glsl_permutation_s *hashnext;
705         unsigned int mode;
706         unsigned int permutation;
707
708         /// indicates if we have tried compiling this permutation already
709         qboolean compiled;
710         /// 0 if compilation failed
711         int program;
712         // texture units assigned to each detected uniform
713         int tex_Texture_First;
714         int tex_Texture_Second;
715         int tex_Texture_GammaRamps;
716         int tex_Texture_Normal;
717         int tex_Texture_Color;
718         int tex_Texture_Gloss;
719         int tex_Texture_Glow;
720         int tex_Texture_SecondaryNormal;
721         int tex_Texture_SecondaryColor;
722         int tex_Texture_SecondaryGloss;
723         int tex_Texture_SecondaryGlow;
724         int tex_Texture_Pants;
725         int tex_Texture_Shirt;
726         int tex_Texture_FogHeightTexture;
727         int tex_Texture_FogMask;
728         int tex_Texture_Lightmap;
729         int tex_Texture_Deluxemap;
730         int tex_Texture_Attenuation;
731         int tex_Texture_Cube;
732         int tex_Texture_Refraction;
733         int tex_Texture_Reflection;
734         int tex_Texture_ShadowMap2D;
735         int tex_Texture_CubeProjection;
736         int tex_Texture_ScreenDepth;
737         int tex_Texture_ScreenNormalMap;
738         int tex_Texture_ScreenDiffuse;
739         int tex_Texture_ScreenSpecular;
740         int tex_Texture_ReflectMask;
741         int tex_Texture_ReflectCube;
742         int tex_Texture_BounceGrid;
743         /// locations of detected uniforms in program object, or -1 if not found
744         int loc_Texture_First;
745         int loc_Texture_Second;
746         int loc_Texture_GammaRamps;
747         int loc_Texture_Normal;
748         int loc_Texture_Color;
749         int loc_Texture_Gloss;
750         int loc_Texture_Glow;
751         int loc_Texture_SecondaryNormal;
752         int loc_Texture_SecondaryColor;
753         int loc_Texture_SecondaryGloss;
754         int loc_Texture_SecondaryGlow;
755         int loc_Texture_Pants;
756         int loc_Texture_Shirt;
757         int loc_Texture_FogHeightTexture;
758         int loc_Texture_FogMask;
759         int loc_Texture_Lightmap;
760         int loc_Texture_Deluxemap;
761         int loc_Texture_Attenuation;
762         int loc_Texture_Cube;
763         int loc_Texture_Refraction;
764         int loc_Texture_Reflection;
765         int loc_Texture_ShadowMap2D;
766         int loc_Texture_CubeProjection;
767         int loc_Texture_ScreenDepth;
768         int loc_Texture_ScreenNormalMap;
769         int loc_Texture_ScreenDiffuse;
770         int loc_Texture_ScreenSpecular;
771         int loc_Texture_ReflectMask;
772         int loc_Texture_ReflectCube;
773         int loc_Texture_BounceGrid;
774         int loc_Alpha;
775         int loc_BloomBlur_Parameters;
776         int loc_ClientTime;
777         int loc_Color_Ambient;
778         int loc_Color_Diffuse;
779         int loc_Color_Specular;
780         int loc_Color_Glow;
781         int loc_Color_Pants;
782         int loc_Color_Shirt;
783         int loc_DeferredColor_Ambient;
784         int loc_DeferredColor_Diffuse;
785         int loc_DeferredColor_Specular;
786         int loc_DeferredMod_Diffuse;
787         int loc_DeferredMod_Specular;
788         int loc_DistortScaleRefractReflect;
789         int loc_EyePosition;
790         int loc_FogColor;
791         int loc_FogHeightFade;
792         int loc_FogPlane;
793         int loc_FogPlaneViewDist;
794         int loc_FogRangeRecip;
795         int loc_LightColor;
796         int loc_LightDir;
797         int loc_LightPosition;
798         int loc_OffsetMapping_Scale;
799         int loc_PixelSize;
800         int loc_ReflectColor;
801         int loc_ReflectFactor;
802         int loc_ReflectOffset;
803         int loc_RefractColor;
804         int loc_Saturation;
805         int loc_ScreenCenterRefractReflect;
806         int loc_ScreenScaleRefractReflect;
807         int loc_ScreenToDepth;
808         int loc_ShadowMap_Parameters;
809         int loc_ShadowMap_TextureScale;
810         int loc_SpecularPower;
811         int loc_UserVec1;
812         int loc_UserVec2;
813         int loc_UserVec3;
814         int loc_UserVec4;
815         int loc_ViewTintColor;
816         int loc_ViewToLight;
817         int loc_ModelToLight;
818         int loc_TexMatrix;
819         int loc_BackgroundTexMatrix;
820         int loc_ModelViewProjectionMatrix;
821         int loc_ModelViewMatrix;
822         int loc_PixelToScreenTexCoord;
823         int loc_ModelToReflectCube;
824         int loc_ShadowMapMatrix;
825         int loc_BloomColorSubtract;
826         int loc_NormalmapScrollBlend;
827         int loc_BounceGridMatrix;
828         int loc_BounceGridIntensity;
829 }
830 r_glsl_permutation_t;
831
832 #define SHADERPERMUTATION_HASHSIZE 256
833
834
835 // non-degradable "lightweight" shader parameters to keep the permutations simpler
836 // these can NOT degrade! only use for simple stuff
837 enum
838 {
839         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
840         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
841         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
842         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
843         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
844         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
845 };
846 #define SHADERSTATICPARMS_COUNT 6
847
848 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
849 static int shaderstaticparms_count = 0;
850
851 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
852 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
853 qboolean R_CompileShader_CheckStaticParms(void)
854 {
855         static int r_compileshader_staticparms_save[1];
856         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
857         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
858
859         // detect all
860         if (r_glsl_saturation_redcompensate.integer)
861                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
862         if (r_shadow_glossexact.integer)
863                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
864         if (r_glsl_postprocess.integer)
865         {
866                 if (r_glsl_postprocess_uservec1_enable.integer)
867                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
868                 if (r_glsl_postprocess_uservec2_enable.integer)
869                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
870                 if (r_glsl_postprocess_uservec3_enable.integer)
871                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
872                 if (r_glsl_postprocess_uservec4_enable.integer)
873                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
874         }
875         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
876 }
877
878 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
879         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
880                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
881         else \
882                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
883 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
884 {
885         shaderstaticparms_count = 0;
886
887         // emit all
888         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
889         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
890         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
891         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
892         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
893         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
894 }
895
896 /// information about each possible shader permutation
897 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
898 /// currently selected permutation
899 r_glsl_permutation_t *r_glsl_permutation;
900 /// storage for permutations linked in the hash table
901 memexpandablearray_t r_glsl_permutationarray;
902
903 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
904 {
905         //unsigned int hashdepth = 0;
906         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
907         r_glsl_permutation_t *p;
908         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
909         {
910                 if (p->mode == mode && p->permutation == permutation)
911                 {
912                         //if (hashdepth > 10)
913                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
914                         return p;
915                 }
916                 //hashdepth++;
917         }
918         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
919         p->mode = mode;
920         p->permutation = permutation;
921         p->hashnext = r_glsl_permutationhash[mode][hashindex];
922         r_glsl_permutationhash[mode][hashindex] = p;
923         //if (hashdepth > 10)
924         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
925         return p;
926 }
927
928 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
929 {
930         char *shaderstring;
931         if (!filename || !filename[0])
932                 return NULL;
933         if (!strcmp(filename, "glsl/default.glsl"))
934         {
935                 if (!glslshaderstring)
936                 {
937                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
938                         if (glslshaderstring)
939                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
940                         else
941                                 glslshaderstring = (char *)builtinshaderstring;
942                 }
943                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
944                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
945                 return shaderstring;
946         }
947         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
948         if (shaderstring)
949         {
950                 if (printfromdisknotice)
951                         Con_DPrintf("from disk %s... ", filename);
952                 return shaderstring;
953         }
954         return shaderstring;
955 }
956
957 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
958 {
959         int i;
960         int sampler;
961         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
962         char *vertexstring, *geometrystring, *fragmentstring;
963         char permutationname[256];
964         int vertstrings_count = 0;
965         int geomstrings_count = 0;
966         int fragstrings_count = 0;
967         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
968         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
969         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
970
971         if (p->compiled)
972                 return;
973         p->compiled = true;
974         p->program = 0;
975
976         permutationname[0] = 0;
977         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
978         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
979         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
980
981         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
982
983         // the first pretext is which type of shader to compile as
984         // (later these will all be bound together as a program object)
985         if(qglBindFragDataLocation && (permutation & SHADERPERMUTATION_OFFSETMAPPING)) // we use textureGrad() which is glsl 1.30
986         {
987                 vertstrings_list[vertstrings_count++] = "#version 130\n";
988                 geomstrings_list[geomstrings_count++] = "#version 130\n";
989                 fragstrings_list[fragstrings_count++] = "#version 130\n";
990         }
991
992         // the first pretext is which type of shader to compile as
993         // (later these will all be bound together as a program object)
994         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
995         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
996         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
997
998         // the second pretext is the mode (for example a light source)
999         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1000         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1001         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1002         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1003
1004         // now add all the permutation pretexts
1005         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1006         {
1007                 if (permutation & (1<<i))
1008                 {
1009                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1010                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1011                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1012                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1013                 }
1014                 else
1015                 {
1016                         // keep line numbers correct
1017                         vertstrings_list[vertstrings_count++] = "\n";
1018                         geomstrings_list[geomstrings_count++] = "\n";
1019                         fragstrings_list[fragstrings_count++] = "\n";
1020                 }
1021         }
1022
1023         // add static parms
1024         R_CompileShader_AddStaticParms(mode, permutation);
1025         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1026         vertstrings_count += shaderstaticparms_count;
1027         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1028         geomstrings_count += shaderstaticparms_count;
1029         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1030         fragstrings_count += shaderstaticparms_count;
1031
1032         // now append the shader text itself
1033         vertstrings_list[vertstrings_count++] = vertexstring;
1034         geomstrings_list[geomstrings_count++] = geometrystring;
1035         fragstrings_list[fragstrings_count++] = fragmentstring;
1036
1037         // if any sources were NULL, clear the respective list
1038         if (!vertexstring)
1039                 vertstrings_count = 0;
1040         if (!geometrystring)
1041                 geomstrings_count = 0;
1042         if (!fragmentstring)
1043                 fragstrings_count = 0;
1044
1045         // compile the shader program
1046         if (vertstrings_count + geomstrings_count + fragstrings_count)
1047                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1048         if (p->program)
1049         {
1050                 CHECKGLERROR
1051                 qglUseProgram(p->program);CHECKGLERROR
1052                 // look up all the uniform variable names we care about, so we don't
1053                 // have to look them up every time we set them
1054
1055                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1056                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1057                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1058                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1059                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1060                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1061                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1062                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1063                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1064                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1065                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1066                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1067                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1068                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1069                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1070                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1071                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1072                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1073                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1074                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1075                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1076                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1077                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1078                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1079                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1080                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1081                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1082                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1083                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1084                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1085                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1086                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1087                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1088                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1089                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1090                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1091                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1092                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1093                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1094                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1095                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1096                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1097                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1098                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1099                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1100                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1101                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1102                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1103                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1104                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1105                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1106                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1107                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1108                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1109                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
1110                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1111                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1112                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1113                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1114                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1115                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1116                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1117                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1118                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1119                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1120                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1121                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1122                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1123                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1124                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1125                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1126                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1127                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1128                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1129                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1130                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1131                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1132                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1133                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1134                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1135                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1136                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1137                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1138                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1139                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1140                 // initialize the samplers to refer to the texture units we use
1141                 p->tex_Texture_First = -1;
1142                 p->tex_Texture_Second = -1;
1143                 p->tex_Texture_GammaRamps = -1;
1144                 p->tex_Texture_Normal = -1;
1145                 p->tex_Texture_Color = -1;
1146                 p->tex_Texture_Gloss = -1;
1147                 p->tex_Texture_Glow = -1;
1148                 p->tex_Texture_SecondaryNormal = -1;
1149                 p->tex_Texture_SecondaryColor = -1;
1150                 p->tex_Texture_SecondaryGloss = -1;
1151                 p->tex_Texture_SecondaryGlow = -1;
1152                 p->tex_Texture_Pants = -1;
1153                 p->tex_Texture_Shirt = -1;
1154                 p->tex_Texture_FogHeightTexture = -1;
1155                 p->tex_Texture_FogMask = -1;
1156                 p->tex_Texture_Lightmap = -1;
1157                 p->tex_Texture_Deluxemap = -1;
1158                 p->tex_Texture_Attenuation = -1;
1159                 p->tex_Texture_Cube = -1;
1160                 p->tex_Texture_Refraction = -1;
1161                 p->tex_Texture_Reflection = -1;
1162                 p->tex_Texture_ShadowMap2D = -1;
1163                 p->tex_Texture_CubeProjection = -1;
1164                 p->tex_Texture_ScreenDepth = -1;
1165                 p->tex_Texture_ScreenNormalMap = -1;
1166                 p->tex_Texture_ScreenDiffuse = -1;
1167                 p->tex_Texture_ScreenSpecular = -1;
1168                 p->tex_Texture_ReflectMask = -1;
1169                 p->tex_Texture_ReflectCube = -1;
1170                 p->tex_Texture_BounceGrid = -1;
1171                 sampler = 0;
1172                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1173                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1174                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1175                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1176                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1177                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1178                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1179                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1180                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1181                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1182                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1183                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1184                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1185                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1186                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1187                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1188                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1189                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1190                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1191                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1192                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1193                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1194                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1195                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1196                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1197                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1198                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1199                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1200                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1201                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1202                 CHECKGLERROR
1203                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1204         }
1205         else
1206                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1207
1208         // free the strings
1209         if (vertexstring)
1210                 Mem_Free(vertexstring);
1211         if (geometrystring)
1212                 Mem_Free(geometrystring);
1213         if (fragmentstring)
1214                 Mem_Free(fragmentstring);
1215 }
1216
1217 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1218 {
1219         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1220         if (r_glsl_permutation != perm)
1221         {
1222                 r_glsl_permutation = perm;
1223                 if (!r_glsl_permutation->program)
1224                 {
1225                         if (!r_glsl_permutation->compiled)
1226                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1227                         if (!r_glsl_permutation->program)
1228                         {
1229                                 // remove features until we find a valid permutation
1230                                 int i;
1231                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1232                                 {
1233                                         // reduce i more quickly whenever it would not remove any bits
1234                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1235                                         if (!(permutation & j))
1236                                                 continue;
1237                                         permutation -= j;
1238                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1239                                         if (!r_glsl_permutation->compiled)
1240                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1241                                         if (r_glsl_permutation->program)
1242                                                 break;
1243                                 }
1244                                 if (i >= SHADERPERMUTATION_COUNT)
1245                                 {
1246                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1247                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1248                                         qglUseProgram(0);CHECKGLERROR
1249                                         return; // no bit left to clear, entire mode is broken
1250                                 }
1251                         }
1252                 }
1253                 CHECKGLERROR
1254                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1255         }
1256         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1257         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1258         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1259 }
1260
1261 #ifdef SUPPORTD3D
1262
1263 #ifdef SUPPORTD3D
1264 #include <d3d9.h>
1265 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1266 extern D3DCAPS9 vid_d3d9caps;
1267 #endif
1268
1269 struct r_hlsl_permutation_s;
1270 typedef struct r_hlsl_permutation_s
1271 {
1272         /// hash lookup data
1273         struct r_hlsl_permutation_s *hashnext;
1274         unsigned int mode;
1275         unsigned int permutation;
1276
1277         /// indicates if we have tried compiling this permutation already
1278         qboolean compiled;
1279         /// NULL if compilation failed
1280         IDirect3DVertexShader9 *vertexshader;
1281         IDirect3DPixelShader9 *pixelshader;
1282 }
1283 r_hlsl_permutation_t;
1284
1285 typedef enum D3DVSREGISTER_e
1286 {
1287         D3DVSREGISTER_TexMatrix = 0, // float4x4
1288         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1289         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1290         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1291         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1292         D3DVSREGISTER_ModelToLight = 20, // float4x4
1293         D3DVSREGISTER_EyePosition = 24,
1294         D3DVSREGISTER_FogPlane = 25,
1295         D3DVSREGISTER_LightDir = 26,
1296         D3DVSREGISTER_LightPosition = 27,
1297 }
1298 D3DVSREGISTER_t;
1299
1300 typedef enum D3DPSREGISTER_e
1301 {
1302         D3DPSREGISTER_Alpha = 0,
1303         D3DPSREGISTER_BloomBlur_Parameters = 1,
1304         D3DPSREGISTER_ClientTime = 2,
1305         D3DPSREGISTER_Color_Ambient = 3,
1306         D3DPSREGISTER_Color_Diffuse = 4,
1307         D3DPSREGISTER_Color_Specular = 5,
1308         D3DPSREGISTER_Color_Glow = 6,
1309         D3DPSREGISTER_Color_Pants = 7,
1310         D3DPSREGISTER_Color_Shirt = 8,
1311         D3DPSREGISTER_DeferredColor_Ambient = 9,
1312         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1313         D3DPSREGISTER_DeferredColor_Specular = 11,
1314         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1315         D3DPSREGISTER_DeferredMod_Specular = 13,
1316         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1317         D3DPSREGISTER_EyePosition = 15, // unused
1318         D3DPSREGISTER_FogColor = 16,
1319         D3DPSREGISTER_FogHeightFade = 17,
1320         D3DPSREGISTER_FogPlane = 18,
1321         D3DPSREGISTER_FogPlaneViewDist = 19,
1322         D3DPSREGISTER_FogRangeRecip = 20,
1323         D3DPSREGISTER_LightColor = 21,
1324         D3DPSREGISTER_LightDir = 22, // unused
1325         D3DPSREGISTER_LightPosition = 23,
1326         D3DPSREGISTER_OffsetMapping_Scale = 24,
1327         D3DPSREGISTER_PixelSize = 25,
1328         D3DPSREGISTER_ReflectColor = 26,
1329         D3DPSREGISTER_ReflectFactor = 27,
1330         D3DPSREGISTER_ReflectOffset = 28,
1331         D3DPSREGISTER_RefractColor = 29,
1332         D3DPSREGISTER_Saturation = 30,
1333         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1334         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1335         D3DPSREGISTER_ScreenToDepth = 33,
1336         D3DPSREGISTER_ShadowMap_Parameters = 34,
1337         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1338         D3DPSREGISTER_SpecularPower = 36,
1339         D3DPSREGISTER_UserVec1 = 37,
1340         D3DPSREGISTER_UserVec2 = 38,
1341         D3DPSREGISTER_UserVec3 = 39,
1342         D3DPSREGISTER_UserVec4 = 40,
1343         D3DPSREGISTER_ViewTintColor = 41,
1344         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1345         D3DPSREGISTER_BloomColorSubtract = 43,
1346         D3DPSREGISTER_ViewToLight = 44, // float4x4
1347         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1348         D3DPSREGISTER_NormalmapScrollBlend = 52,
1349         // next at 53
1350 }
1351 D3DPSREGISTER_t;
1352
1353 /// information about each possible shader permutation
1354 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1355 /// currently selected permutation
1356 r_hlsl_permutation_t *r_hlsl_permutation;
1357 /// storage for permutations linked in the hash table
1358 memexpandablearray_t r_hlsl_permutationarray;
1359
1360 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1361 {
1362         //unsigned int hashdepth = 0;
1363         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1364         r_hlsl_permutation_t *p;
1365         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1366         {
1367                 if (p->mode == mode && p->permutation == permutation)
1368                 {
1369                         //if (hashdepth > 10)
1370                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1371                         return p;
1372                 }
1373                 //hashdepth++;
1374         }
1375         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1376         p->mode = mode;
1377         p->permutation = permutation;
1378         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1379         r_hlsl_permutationhash[mode][hashindex] = p;
1380         //if (hashdepth > 10)
1381         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1382         return p;
1383 }
1384
1385 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1386 {
1387         char *shaderstring;
1388         if (!filename || !filename[0])
1389                 return NULL;
1390         if (!strcmp(filename, "hlsl/default.hlsl"))
1391         {
1392                 if (!hlslshaderstring)
1393                 {
1394                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1395                         if (hlslshaderstring)
1396                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1397                         else
1398                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1399                 }
1400                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1401                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1402                 return shaderstring;
1403         }
1404         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1405         if (shaderstring)
1406         {
1407                 if (printfromdisknotice)
1408                         Con_DPrintf("from disk %s... ", filename);
1409                 return shaderstring;
1410         }
1411         return shaderstring;
1412 }
1413
1414 #include <d3dx9.h>
1415 //#include <d3dx9shader.h>
1416 //#include <d3dx9mesh.h>
1417
1418 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1419 {
1420         DWORD *vsbin = NULL;
1421         DWORD *psbin = NULL;
1422         fs_offset_t vsbinsize;
1423         fs_offset_t psbinsize;
1424 //      IDirect3DVertexShader9 *vs = NULL;
1425 //      IDirect3DPixelShader9 *ps = NULL;
1426         ID3DXBuffer *vslog = NULL;
1427         ID3DXBuffer *vsbuffer = NULL;
1428         ID3DXConstantTable *vsconstanttable = NULL;
1429         ID3DXBuffer *pslog = NULL;
1430         ID3DXBuffer *psbuffer = NULL;
1431         ID3DXConstantTable *psconstanttable = NULL;
1432         int vsresult = 0;
1433         int psresult = 0;
1434         char temp[MAX_INPUTLINE];
1435         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1436         qboolean debugshader = gl_paranoid.integer != 0;
1437         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1438         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1439         if (!debugshader)
1440         {
1441                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1442                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1443         }
1444         if ((!vsbin && vertstring) || (!psbin && fragstring))
1445         {
1446                 const char* dllnames_d3dx9 [] =
1447                 {
1448                         "d3dx9_43.dll",
1449                         "d3dx9_42.dll",
1450                         "d3dx9_41.dll",
1451                         "d3dx9_40.dll",
1452                         "d3dx9_39.dll",
1453                         "d3dx9_38.dll",
1454                         "d3dx9_37.dll",
1455                         "d3dx9_36.dll",
1456                         "d3dx9_35.dll",
1457                         "d3dx9_34.dll",
1458                         "d3dx9_33.dll",
1459                         "d3dx9_32.dll",
1460                         "d3dx9_31.dll",
1461                         "d3dx9_30.dll",
1462                         "d3dx9_29.dll",
1463                         "d3dx9_28.dll",
1464                         "d3dx9_27.dll",
1465                         "d3dx9_26.dll",
1466                         "d3dx9_25.dll",
1467                         "d3dx9_24.dll",
1468                         NULL
1469                 };
1470                 dllhandle_t d3dx9_dll = NULL;
1471                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1472                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1473                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1474                 dllfunction_t d3dx9_dllfuncs[] =
1475                 {
1476                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1477                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1478                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1479                         {NULL, NULL}
1480                 };
1481                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1482                 {
1483                         DWORD shaderflags = 0;
1484                         if (debugshader)
1485                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1486                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1487                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1488                         if (vertstring && vertstring[0])
1489                         {
1490                                 if (debugshader)
1491                                 {
1492 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1493 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1494                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1495                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1496                                 }
1497                                 else
1498                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1499                                 if (vsbuffer)
1500                                 {
1501                                         vsbinsize = vsbuffer->GetBufferSize();
1502                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1503                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1504                                         vsbuffer->Release();
1505                                 }
1506                                 if (vslog)
1507                                 {
1508                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1509                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1510                                         vslog->Release();
1511                                 }
1512                         }
1513                         if (fragstring && fragstring[0])
1514                         {
1515                                 if (debugshader)
1516                                 {
1517 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1518 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1519                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1520                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1521                                 }
1522                                 else
1523                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1524                                 if (psbuffer)
1525                                 {
1526                                         psbinsize = psbuffer->GetBufferSize();
1527                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1528                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1529                                         psbuffer->Release();
1530                                 }
1531                                 if (pslog)
1532                                 {
1533                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1534                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1535                                         pslog->Release();
1536                                 }
1537                         }
1538                         Sys_UnloadLibrary(&d3dx9_dll);
1539                 }
1540                 else
1541                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1542         }
1543         if (vsbin && psbin)
1544         {
1545                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1546                 if (FAILED(vsresult))
1547                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1548                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1549                 if (FAILED(psresult))
1550                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1551         }
1552         // free the shader data
1553         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1554         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1555 }
1556
1557 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1558 {
1559         int i;
1560         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1561         int vertstring_length = 0;
1562         int geomstring_length = 0;
1563         int fragstring_length = 0;
1564         char *t;
1565         char *vertexstring, *geometrystring, *fragmentstring;
1566         char *vertstring, *geomstring, *fragstring;
1567         char permutationname[256];
1568         char cachename[256];
1569         int vertstrings_count = 0;
1570         int geomstrings_count = 0;
1571         int fragstrings_count = 0;
1572         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1573         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1574         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1575
1576         if (p->compiled)
1577                 return;
1578         p->compiled = true;
1579         p->vertexshader = NULL;
1580         p->pixelshader = NULL;
1581
1582         permutationname[0] = 0;
1583         cachename[0] = 0;
1584         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1585         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1586         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1587
1588         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1589         strlcat(cachename, "hlsl/", sizeof(cachename));
1590
1591         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1592         vertstrings_count = 0;
1593         geomstrings_count = 0;
1594         fragstrings_count = 0;
1595         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1596         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1597         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1598
1599         // the first pretext is which type of shader to compile as
1600         // (later these will all be bound together as a program object)
1601         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1602         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1603         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1604
1605         // the second pretext is the mode (for example a light source)
1606         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1607         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1608         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1609         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1610         strlcat(cachename, modeinfo->name, sizeof(cachename));
1611
1612         // now add all the permutation pretexts
1613         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1614         {
1615                 if (permutation & (1<<i))
1616                 {
1617                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1618                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1619                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1620                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1621                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1622                 }
1623                 else
1624                 {
1625                         // keep line numbers correct
1626                         vertstrings_list[vertstrings_count++] = "\n";
1627                         geomstrings_list[geomstrings_count++] = "\n";
1628                         fragstrings_list[fragstrings_count++] = "\n";
1629                 }
1630         }
1631
1632         // add static parms
1633         R_CompileShader_AddStaticParms(mode, permutation);
1634         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1635         vertstrings_count += shaderstaticparms_count;
1636         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1637         geomstrings_count += shaderstaticparms_count;
1638         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1639         fragstrings_count += shaderstaticparms_count;
1640
1641         // replace spaces in the cachename with _ characters
1642         for (i = 0;cachename[i];i++)
1643                 if (cachename[i] == ' ')
1644                         cachename[i] = '_';
1645
1646         // now append the shader text itself
1647         vertstrings_list[vertstrings_count++] = vertexstring;
1648         geomstrings_list[geomstrings_count++] = geometrystring;
1649         fragstrings_list[fragstrings_count++] = fragmentstring;
1650
1651         // if any sources were NULL, clear the respective list
1652         if (!vertexstring)
1653                 vertstrings_count = 0;
1654         if (!geometrystring)
1655                 geomstrings_count = 0;
1656         if (!fragmentstring)
1657                 fragstrings_count = 0;
1658
1659         vertstring_length = 0;
1660         for (i = 0;i < vertstrings_count;i++)
1661                 vertstring_length += strlen(vertstrings_list[i]);
1662         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1663         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1664                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1665
1666         geomstring_length = 0;
1667         for (i = 0;i < geomstrings_count;i++)
1668                 geomstring_length += strlen(geomstrings_list[i]);
1669         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1670         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1671                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1672
1673         fragstring_length = 0;
1674         for (i = 0;i < fragstrings_count;i++)
1675                 fragstring_length += strlen(fragstrings_list[i]);
1676         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1677         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1678                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1679
1680         // try to load the cached shader, or generate one
1681         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1682
1683         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1684                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1685         else
1686                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1687
1688         // free the strings
1689         if (vertstring)
1690                 Mem_Free(vertstring);
1691         if (geomstring)
1692                 Mem_Free(geomstring);
1693         if (fragstring)
1694                 Mem_Free(fragstring);
1695         if (vertexstring)
1696                 Mem_Free(vertexstring);
1697         if (geometrystring)
1698                 Mem_Free(geometrystring);
1699         if (fragmentstring)
1700                 Mem_Free(fragmentstring);
1701 }
1702
1703 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1704 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1705 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);}
1706 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);}
1707 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);}
1708 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);}
1709
1710 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1711 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1712 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);}
1713 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);}
1714 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);}
1715 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);}
1716
1717 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1718 {
1719         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1720         if (r_hlsl_permutation != perm)
1721         {
1722                 r_hlsl_permutation = perm;
1723                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1724                 {
1725                         if (!r_hlsl_permutation->compiled)
1726                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1727                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1728                         {
1729                                 // remove features until we find a valid permutation
1730                                 int i;
1731                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1732                                 {
1733                                         // reduce i more quickly whenever it would not remove any bits
1734                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1735                                         if (!(permutation & j))
1736                                                 continue;
1737                                         permutation -= j;
1738                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1739                                         if (!r_hlsl_permutation->compiled)
1740                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1741                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1742                                                 break;
1743                                 }
1744                                 if (i >= SHADERPERMUTATION_COUNT)
1745                                 {
1746                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1747                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1748                                         return; // no bit left to clear, entire mode is broken
1749                                 }
1750                         }
1751                 }
1752                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1753                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1754         }
1755         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1756         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1757         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1758 }
1759 #endif
1760
1761 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1762 {
1763         DPSOFTRAST_SetShader(mode, permutation);
1764         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1765         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1766         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1767 }
1768
1769 void R_GLSL_Restart_f(void)
1770 {
1771         unsigned int i, limit;
1772         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1773                 Mem_Free(glslshaderstring);
1774         glslshaderstring = NULL;
1775         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1776                 Mem_Free(hlslshaderstring);
1777         hlslshaderstring = NULL;
1778         switch(vid.renderpath)
1779         {
1780         case RENDERPATH_D3D9:
1781 #ifdef SUPPORTD3D
1782                 {
1783                         r_hlsl_permutation_t *p;
1784                         r_hlsl_permutation = NULL;
1785                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1786                         for (i = 0;i < limit;i++)
1787                         {
1788                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1789                                 {
1790                                         if (p->vertexshader)
1791                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1792                                         if (p->pixelshader)
1793                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1794                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1795                                 }
1796                         }
1797                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1798                 }
1799 #endif
1800                 break;
1801         case RENDERPATH_D3D10:
1802                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1803                 break;
1804         case RENDERPATH_D3D11:
1805                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1806                 break;
1807         case RENDERPATH_GL20:
1808         case RENDERPATH_GLES2:
1809                 {
1810                         r_glsl_permutation_t *p;
1811                         r_glsl_permutation = NULL;
1812                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1813                         for (i = 0;i < limit;i++)
1814                         {
1815                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1816                                 {
1817                                         GL_Backend_FreeProgram(p->program);
1818                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1819                                 }
1820                         }
1821                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1822                 }
1823                 break;
1824         case RENDERPATH_GL13:
1825         case RENDERPATH_GL11:
1826                 break;
1827         case RENDERPATH_SOFT:
1828                 break;
1829         }
1830 }
1831
1832 void R_GLSL_DumpShader_f(void)
1833 {
1834         int i;
1835         qfile_t *file;
1836
1837         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1838         if (file)
1839         {
1840                 FS_Print(file, "/* The engine may define the following macros:\n");
1841                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1842                 for (i = 0;i < SHADERMODE_COUNT;i++)
1843                         FS_Print(file, glslshadermodeinfo[i].pretext);
1844                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1845                         FS_Print(file, shaderpermutationinfo[i].pretext);
1846                 FS_Print(file, "*/\n");
1847                 FS_Print(file, builtinshaderstring);
1848                 FS_Close(file);
1849                 Con_Printf("glsl/default.glsl written\n");
1850         }
1851         else
1852                 Con_Printf("failed to write to glsl/default.glsl\n");
1853
1854         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1855         if (file)
1856         {
1857                 FS_Print(file, "/* The engine may define the following macros:\n");
1858                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1859                 for (i = 0;i < SHADERMODE_COUNT;i++)
1860                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1861                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1862                         FS_Print(file, shaderpermutationinfo[i].pretext);
1863                 FS_Print(file, "*/\n");
1864                 FS_Print(file, builtinhlslshaderstring);
1865                 FS_Close(file);
1866                 Con_Printf("hlsl/default.hlsl written\n");
1867         }
1868         else
1869                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1870 }
1871
1872 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1873 {
1874         if (!second)
1875                 texturemode = GL_MODULATE;
1876         switch (vid.renderpath)
1877         {
1878         case RENDERPATH_D3D9:
1879 #ifdef SUPPORTD3D
1880                 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))));
1881                 R_Mesh_TexBind(GL20TU_FIRST , first );
1882                 R_Mesh_TexBind(GL20TU_SECOND, second);
1883 #endif
1884                 break;
1885         case RENDERPATH_D3D10:
1886                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1887                 break;
1888         case RENDERPATH_D3D11:
1889                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1890                 break;
1891         case RENDERPATH_GL20:
1892         case RENDERPATH_GLES2:
1893                 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))));
1894                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1895                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1896                 break;
1897         case RENDERPATH_GL13:
1898                 R_Mesh_TexBind(0, first );
1899                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1900                 R_Mesh_TexBind(1, second);
1901                 if (second)
1902                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1903                 break;
1904         case RENDERPATH_GL11:
1905                 R_Mesh_TexBind(0, first );
1906                 break;
1907         case RENDERPATH_SOFT:
1908                 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))));
1909                 R_Mesh_TexBind(GL20TU_FIRST , first );
1910                 R_Mesh_TexBind(GL20TU_SECOND, second);
1911                 break;
1912         }
1913 }
1914
1915 void R_SetupShader_DepthOrShadow(void)
1916 {
1917         switch (vid.renderpath)
1918         {
1919         case RENDERPATH_D3D9:
1920 #ifdef SUPPORTD3D
1921                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1922 #endif
1923                 break;
1924         case RENDERPATH_D3D10:
1925                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1926                 break;
1927         case RENDERPATH_D3D11:
1928                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1929                 break;
1930         case RENDERPATH_GL20:
1931         case RENDERPATH_GLES2:
1932                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1933                 break;
1934         case RENDERPATH_GL13:
1935                 R_Mesh_TexBind(0, 0);
1936                 R_Mesh_TexBind(1, 0);
1937                 break;
1938         case RENDERPATH_GL11:
1939                 R_Mesh_TexBind(0, 0);
1940                 break;
1941         case RENDERPATH_SOFT:
1942                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1943                 break;
1944         }
1945 }
1946
1947 void R_SetupShader_ShowDepth(void)
1948 {
1949         switch (vid.renderpath)
1950         {
1951         case RENDERPATH_D3D9:
1952 #ifdef SUPPORTHLSL
1953                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1954 #endif
1955                 break;
1956         case RENDERPATH_D3D10:
1957                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958                 break;
1959         case RENDERPATH_D3D11:
1960                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961                 break;
1962         case RENDERPATH_GL20:
1963         case RENDERPATH_GLES2:
1964                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1965                 break;
1966         case RENDERPATH_GL13:
1967                 break;
1968         case RENDERPATH_GL11:
1969                 break;
1970         case RENDERPATH_SOFT:
1971                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1972                 break;
1973         }
1974 }
1975
1976 extern qboolean r_shadow_usingdeferredprepass;
1977 extern cvar_t r_shadow_deferred_8bitrange;
1978 extern rtexture_t *r_shadow_attenuationgradienttexture;
1979 extern rtexture_t *r_shadow_attenuation2dtexture;
1980 extern rtexture_t *r_shadow_attenuation3dtexture;
1981 extern qboolean r_shadow_usingshadowmap2d;
1982 extern qboolean r_shadow_usingshadowmaportho;
1983 extern float r_shadow_shadowmap_texturescale[2];
1984 extern float r_shadow_shadowmap_parameters[4];
1985 extern qboolean r_shadow_shadowmapvsdct;
1986 extern qboolean r_shadow_shadowmapsampler;
1987 extern int r_shadow_shadowmappcf;
1988 extern rtexture_t *r_shadow_shadowmap2dtexture;
1989 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1990 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1991 extern matrix4x4_t r_shadow_shadowmapmatrix;
1992 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1993 extern int r_shadow_prepass_width;
1994 extern int r_shadow_prepass_height;
1995 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1996 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1997 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
1998 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
1999 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2000
2001 #define BLENDFUNC_ALLOWS_COLORMOD      1
2002 #define BLENDFUNC_ALLOWS_FOG           2
2003 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2004 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2005 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2006 static int R_BlendFuncFlags(int src, int dst)
2007 {
2008         int r = 0;
2009
2010         // a blendfunc allows colormod if:
2011         // a) it can never keep the destination pixel invariant, or
2012         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2013         // this is to prevent unintended side effects from colormod
2014
2015         // a blendfunc allows fog if:
2016         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2017         // this is to prevent unintended side effects from fog
2018
2019         // these checks are the output of fogeval.pl
2020
2021         r |= BLENDFUNC_ALLOWS_COLORMOD;
2022         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2023         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2024         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2025         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2026         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2027         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2028         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2029         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2030         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2031         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2032         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2033         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2034         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2035         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2036         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2037         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2038         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2039         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2040         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2041         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2042         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2043
2044         return r;
2045 }
2046
2047 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)
2048 {
2049         // select a permutation of the lighting shader appropriate to this
2050         // combination of texture, entity, light source, and fogging, only use the
2051         // minimum features necessary to avoid wasting rendering time in the
2052         // fragment shader on features that are not being used
2053         unsigned int permutation = 0;
2054         unsigned int mode = 0;
2055         int blendfuncflags;
2056         static float dummy_colormod[3] = {1, 1, 1};
2057         float *colormod = rsurface.colormod;
2058         float m16f[16];
2059         matrix4x4_t tempmatrix;
2060         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2061         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2062                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2063         if (rsurfacepass == RSURFPASS_BACKGROUND)
2064         {
2065                 // distorted background
2066                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2067                 {
2068                         mode = SHADERMODE_WATER;
2069                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2070                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2071                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2072                         {
2073                                 // this is the right thing to do for wateralpha
2074                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2075                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2076                         }
2077                         else
2078                         {
2079                                 // this is the right thing to do for entity alpha
2080                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2081                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2082                         }
2083                 }
2084                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2085                 {
2086                         mode = SHADERMODE_REFRACTION;
2087                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2088                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2089                 }
2090                 else
2091                 {
2092                         mode = SHADERMODE_GENERIC;
2093                         permutation |= SHADERPERMUTATION_DIFFUSE;
2094                         GL_BlendFunc(GL_ONE, GL_ZERO);
2095                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2096                 }
2097         }
2098         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2099         {
2100                 if (r_glsl_offsetmapping.integer)
2101                 {
2102                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2103                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2104                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2105                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2106                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2107                         {
2108                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2109                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2110                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2111                         }
2112                 }
2113                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2114                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2115                 // normalmap (deferred prepass), may use alpha test on diffuse
2116                 mode = SHADERMODE_DEFERREDGEOMETRY;
2117                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2118                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2119                 GL_BlendFunc(GL_ONE, GL_ZERO);
2120                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2121         }
2122         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2123         {
2124                 if (r_glsl_offsetmapping.integer)
2125                 {
2126                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2127                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2128                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2129                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2130                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2131                         {
2132                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2133                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2134                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2135                         }
2136                 }
2137                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2138                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2139                 // light source
2140                 mode = SHADERMODE_LIGHTSOURCE;
2141                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2142                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2143                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2144                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2145                 if (diffusescale > 0)
2146                         permutation |= SHADERPERMUTATION_DIFFUSE;
2147                 if (specularscale > 0)
2148                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2149                 if (r_refdef.fogenabled)
2150                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2151                 if (rsurface.texture->colormapping)
2152                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2153                 if (r_shadow_usingshadowmap2d)
2154                 {
2155                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2156                         if(r_shadow_shadowmapvsdct)
2157                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2158
2159                         if (r_shadow_shadowmapsampler)
2160                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2161                         if (r_shadow_shadowmappcf > 1)
2162                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2163                         else if (r_shadow_shadowmappcf)
2164                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2165                 }
2166                 if (rsurface.texture->reflectmasktexture)
2167                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2168                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2169                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2170         }
2171         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2172         {
2173                 if (r_glsl_offsetmapping.integer)
2174                 {
2175                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2176                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2177                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2178                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2179                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2180                         {
2181                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2182                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2183                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2184                         }
2185                 }
2186                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2187                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2188                 // unshaded geometry (fullbright or ambient model lighting)
2189                 mode = SHADERMODE_FLATCOLOR;
2190                 ambientscale = diffusescale = specularscale = 0;
2191                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2192                         permutation |= SHADERPERMUTATION_GLOW;
2193                 if (r_refdef.fogenabled)
2194                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2195                 if (rsurface.texture->colormapping)
2196                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2197                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2198                 {
2199                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2200                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2201
2202                         if (r_shadow_shadowmapsampler)
2203                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2204                         if (r_shadow_shadowmappcf > 1)
2205                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2206                         else if (r_shadow_shadowmappcf)
2207                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2208                 }
2209                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2210                         permutation |= SHADERPERMUTATION_REFLECTION;
2211                 if (rsurface.texture->reflectmasktexture)
2212                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2213                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2214                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2215         }
2216         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2217         {
2218                 if (r_glsl_offsetmapping.integer)
2219                 {
2220                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2221                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2222                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2223                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2224                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2225                         {
2226                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2227                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2228                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2229                         }
2230                 }
2231                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2232                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2233                 // directional model lighting
2234                 mode = SHADERMODE_LIGHTDIRECTION;
2235                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2236                         permutation |= SHADERPERMUTATION_GLOW;
2237                 permutation |= SHADERPERMUTATION_DIFFUSE;
2238                 if (specularscale > 0)
2239                         permutation |= SHADERPERMUTATION_SPECULAR;
2240                 if (r_refdef.fogenabled)
2241                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2242                 if (rsurface.texture->colormapping)
2243                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2244                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2245                 {
2246                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2247                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2248
2249                         if (r_shadow_shadowmapsampler)
2250                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2251                         if (r_shadow_shadowmappcf > 1)
2252                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2253                         else if (r_shadow_shadowmappcf)
2254                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2255                 }
2256                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2257                         permutation |= SHADERPERMUTATION_REFLECTION;
2258                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2259                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2260                 if (rsurface.texture->reflectmasktexture)
2261                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2262                 if (r_shadow_bouncegridtexture)
2263                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2264                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2265                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2266         }
2267         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2268         {
2269                 if (r_glsl_offsetmapping.integer)
2270                 {
2271                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2272                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2273                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2274                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2275                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2276                         {
2277                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2278                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2279                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2280                         }
2281                 }
2282                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2283                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2284                 // ambient model lighting
2285                 mode = SHADERMODE_LIGHTDIRECTION;
2286                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2287                         permutation |= SHADERPERMUTATION_GLOW;
2288                 if (r_refdef.fogenabled)
2289                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2290                 if (rsurface.texture->colormapping)
2291                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2292                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2293                 {
2294                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2295                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2296
2297                         if (r_shadow_shadowmapsampler)
2298                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2299                         if (r_shadow_shadowmappcf > 1)
2300                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2301                         else if (r_shadow_shadowmappcf)
2302                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2303                 }
2304                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2305                         permutation |= SHADERPERMUTATION_REFLECTION;
2306                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2307                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2308                 if (rsurface.texture->reflectmasktexture)
2309                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2310                 if (r_shadow_bouncegridtexture)
2311                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2312                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2313                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2314         }
2315         else
2316         {
2317                 if (r_glsl_offsetmapping.integer)
2318                 {
2319                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2320                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2321                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2322                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2323                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2324                         {
2325                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2326                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2327                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2328                         }
2329                 }
2330                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2331                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2332                 // lightmapped wall
2333                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2334                         permutation |= SHADERPERMUTATION_GLOW;
2335                 if (r_refdef.fogenabled)
2336                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2337                 if (rsurface.texture->colormapping)
2338                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2339                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2340                 {
2341                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2342                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2343
2344                         if (r_shadow_shadowmapsampler)
2345                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2346                         if (r_shadow_shadowmappcf > 1)
2347                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2348                         else if (r_shadow_shadowmappcf)
2349                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2350                 }
2351                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2352                         permutation |= SHADERPERMUTATION_REFLECTION;
2353                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2354                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2355                 if (rsurface.texture->reflectmasktexture)
2356                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2357                 if (FAKELIGHT_ENABLED)
2358                 {
2359                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2360                         mode = SHADERMODE_FAKELIGHT;
2361                         permutation |= SHADERPERMUTATION_DIFFUSE;
2362                         if (specularscale > 0)
2363                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2364                 }
2365                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2366                 {
2367                         // deluxemapping (light direction texture)
2368                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2369                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2370                         else
2371                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2372                         permutation |= SHADERPERMUTATION_DIFFUSE;
2373                         if (specularscale > 0)
2374                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2375                 }
2376                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2377                 {
2378                         // fake deluxemapping (uniform light direction in tangentspace)
2379                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2380                         permutation |= SHADERPERMUTATION_DIFFUSE;
2381                         if (specularscale > 0)
2382                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2383                 }
2384                 else if (rsurface.uselightmaptexture)
2385                 {
2386                         // ordinary lightmapping (q1bsp, q3bsp)
2387                         mode = SHADERMODE_LIGHTMAP;
2388                 }
2389                 else
2390                 {
2391                         // ordinary vertex coloring (q3bsp)
2392                         mode = SHADERMODE_VERTEXCOLOR;
2393                 }
2394                 if (r_shadow_bouncegridtexture)
2395                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2396                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2397                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2398         }
2399         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2400                 colormod = dummy_colormod;
2401         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2402                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2403         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2404                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2405         switch(vid.renderpath)
2406         {
2407         case RENDERPATH_D3D9:
2408 #ifdef SUPPORTD3D
2409                 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);
2410                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2411                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2412                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2413                 if (mode == SHADERMODE_LIGHTSOURCE)
2414                 {
2415                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2416                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2417                 }
2418                 else
2419                 {
2420                         if (mode == SHADERMODE_LIGHTDIRECTION)
2421                         {
2422                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2423                         }
2424                 }
2425                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2426                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2427                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2428                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2429                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2430
2431                 if (mode == SHADERMODE_LIGHTSOURCE)
2432                 {
2433                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2434                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2435                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2436                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2437                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2438
2439                         // additive passes are only darkened by fog, not tinted
2440                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2441                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2442                 }
2443                 else
2444                 {
2445                         if (mode == SHADERMODE_FLATCOLOR)
2446                         {
2447                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2448                         }
2449                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2450                         {
2451                                 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]);
2452                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2453                                 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);
2454                                 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);
2455                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2456                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2457                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2458                         }
2459                         else
2460                         {
2461                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2462                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2463                                 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);
2464                                 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);
2465                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2466                         }
2467                         // additive passes are only darkened by fog, not tinted
2468                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2469                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2470                         else
2471                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2472                         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);
2473                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2474                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2475                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2476                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2477                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2478                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2479                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2480                         if (mode == SHADERMODE_WATER)
2481                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2482                 }
2483                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2484                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2485                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2486                 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));
2487                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2488                 if (rsurface.texture->pantstexture)
2489                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2490                 else
2491                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2492                 if (rsurface.texture->shirttexture)
2493                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2494                 else
2495                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2496                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2497                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2498                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2499                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2500                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2501                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2502                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2503
2504                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2505                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2506                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2507                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2508                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2509                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2510                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2511                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2512                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2513                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2514                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2515                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2516                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2517                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2518                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2519                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2520                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2521                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2522                 {
2523                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2524                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2525                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2526                 }
2527                 else
2528                 {
2529                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2530                 }
2531 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2532 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2533                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2534                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2535                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2536                 {
2537                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2538                         if (rsurface.rtlight)
2539                         {
2540                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2541                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2542                         }
2543                 }
2544 #endif
2545                 break;
2546         case RENDERPATH_D3D10:
2547                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2548                 break;
2549         case RENDERPATH_D3D11:
2550                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2551                 break;
2552         case RENDERPATH_GL20:
2553         case RENDERPATH_GLES2:
2554                 if (!vid.useinterleavedarrays)
2555                 {
2556                         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);
2557                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2558                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2559                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2560                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2561                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2562                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2563                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2564                 }
2565                 else
2566                 {
2567                         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);
2568                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2569                 }
2570                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2571                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2572                 if (mode == SHADERMODE_LIGHTSOURCE)
2573                 {
2574                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2575                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2576                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2577                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2578                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2579                         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);
2580         
2581                         // additive passes are only darkened by fog, not tinted
2582                         if (r_glsl_permutation->loc_FogColor >= 0)
2583                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2584                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2585                 }
2586                 else
2587                 {
2588                         if (mode == SHADERMODE_FLATCOLOR)
2589                         {
2590                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2591                         }
2592                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2593                         {
2594                                 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]);
2595                                 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]);
2596                                 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);
2597                                 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);
2598                                 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);
2599                                 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]);
2600                                 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]);
2601                         }
2602                         else
2603                         {
2604                                 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]);
2605                                 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]);
2606                                 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);
2607                                 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);
2608                                 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);
2609                         }
2610                         // additive passes are only darkened by fog, not tinted
2611                         if (r_glsl_permutation->loc_FogColor >= 0)
2612                         {
2613                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2614                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2615                                 else
2616                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2617                         }
2618                         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);
2619                         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]);
2620                         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]);
2621                         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]);
2622                         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]);
2623                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2624                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2625                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2626                         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]);
2627                 }
2628                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2629                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2630                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2631                 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]);
2632                 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]);
2633
2634                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2635                 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));
2636                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2637                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2638                 {
2639                         if (rsurface.texture->pantstexture)
2640                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2641                         else
2642                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2643                 }
2644                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2645                 {
2646                         if (rsurface.texture->shirttexture)
2647                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2648                         else
2649                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2650                 }
2651                 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]);
2652                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2653                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2654                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2655                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2656                 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]);
2657                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2658                 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);}
2659                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2660
2661                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2662                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2663                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2664                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2665                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2666                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2667                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2668                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2669                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2670                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2671                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2672                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2673                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2674                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2675                 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);
2676                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2677                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2678                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2679                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2680                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2681                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2682                 {
2683                         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);
2684                         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);
2685                         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);
2686                 }
2687                 else
2688                 {
2689                         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);
2690                 }
2691                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2692                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2693                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2694                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2695                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2696                 {
2697                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2698                         if (rsurface.rtlight)
2699                         {
2700                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2701                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2702                         }
2703                 }
2704                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2705                 CHECKGLERROR
2706                 break;
2707         case RENDERPATH_GL13:
2708         case RENDERPATH_GL11:
2709                 break;
2710         case RENDERPATH_SOFT:
2711                 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);
2712                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2713                 R_SetupShader_SetPermutationSoft(mode, permutation);
2714                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2715                 if (mode == SHADERMODE_LIGHTSOURCE)
2716                 {
2717                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2718                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2719                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2720                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2721                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2722                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2723         
2724                         // additive passes are only darkened by fog, not tinted
2725                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2726                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2727                 }
2728                 else
2729                 {
2730                         if (mode == SHADERMODE_FLATCOLOR)
2731                         {
2732                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2733                         }
2734                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2735                         {
2736                                 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]);
2737                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2738                                 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);
2739                                 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);
2740                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2741                                 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]);
2742                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2743                         }
2744                         else
2745                         {
2746                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2747                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2748                                 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);
2749                                 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);
2750                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2751                         }
2752                         // additive passes are only darkened by fog, not tinted
2753                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2754                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2755                         else
2756                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2757                         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);
2758                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2759                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2760                         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]);
2761                         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]);
2762                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2763                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2764                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2765                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2766                 }
2767                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2768                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2769                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2770                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2771                 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]);
2772
2773                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2774                 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));
2775                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2776                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2777                 {
2778                         if (rsurface.texture->pantstexture)
2779                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2780                         else
2781                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2782                 }
2783                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2784                 {
2785                         if (rsurface.texture->shirttexture)
2786                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2787                         else
2788                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2789                 }
2790                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2791                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2792                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2793                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2794                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2795                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2796                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2797
2798                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2799                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2800                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2801                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2802                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2803                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2804                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2805                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2806                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2807                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2808                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2809                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2810                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2811                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2812                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2813                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2814                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2815                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2816                 {
2817                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2818                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2819                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2820                 }
2821                 else
2822                 {
2823                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2824                 }
2825 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2826 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2827                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2828                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2829                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2830                 {
2831                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2832                         if (rsurface.rtlight)
2833                         {
2834                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2835                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2836                         }
2837                 }
2838                 break;
2839         }
2840 }
2841
2842 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2843 {
2844         // select a permutation of the lighting shader appropriate to this
2845         // combination of texture, entity, light source, and fogging, only use the
2846         // minimum features necessary to avoid wasting rendering time in the
2847         // fragment shader on features that are not being used
2848         unsigned int permutation = 0;
2849         unsigned int mode = 0;
2850         const float *lightcolorbase = rtlight->currentcolor;
2851         float ambientscale = rtlight->ambientscale;
2852         float diffusescale = rtlight->diffusescale;
2853         float specularscale = rtlight->specularscale;
2854         // this is the location of the light in view space
2855         vec3_t viewlightorigin;
2856         // this transforms from view space (camera) to light space (cubemap)
2857         matrix4x4_t viewtolight;
2858         matrix4x4_t lighttoview;
2859         float viewtolight16f[16];
2860         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2861         // light source
2862         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2863         if (rtlight->currentcubemap != r_texture_whitecube)
2864                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2865         if (diffusescale > 0)
2866                 permutation |= SHADERPERMUTATION_DIFFUSE;
2867         if (specularscale > 0)
2868                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2869         if (r_shadow_usingshadowmap2d)
2870         {
2871                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2872                 if (r_shadow_shadowmapvsdct)
2873                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2874
2875                 if (r_shadow_shadowmapsampler)
2876                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2877                 if (r_shadow_shadowmappcf > 1)
2878                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2879                 else if (r_shadow_shadowmappcf)
2880                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2881         }
2882         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2883         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2884         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2885         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2886         switch(vid.renderpath)
2887         {
2888         case RENDERPATH_D3D9:
2889 #ifdef SUPPORTD3D
2890                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2891                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2892                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2893                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2894                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2895                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2896                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2897                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2898                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2899                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2900                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2901
2902                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2903                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2904                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2905                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2906                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2907                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2908 #endif
2909                 break;
2910         case RENDERPATH_D3D10:
2911                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2912                 break;
2913         case RENDERPATH_D3D11:
2914                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2915                 break;
2916         case RENDERPATH_GL20:
2917         case RENDERPATH_GLES2:
2918                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2919                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2920                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2921                 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);
2922                 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);
2923                 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);
2924                 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]);
2925                 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]);
2926                 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));
2927                 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]);
2928                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2929
2930                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2931                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2932                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2933                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2934                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2935                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2936                 break;
2937         case RENDERPATH_GL13:
2938         case RENDERPATH_GL11:
2939                 break;
2940         case RENDERPATH_SOFT:
2941                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2942                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2943                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2944                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2945                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2946                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2947                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2948                 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]);
2949                 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));
2950                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2951                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2952
2953                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2954                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2955                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2956                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2957                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2958                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2959                 break;
2960         }
2961 }
2962
2963 #define SKINFRAME_HASH 1024
2964
2965 typedef struct
2966 {
2967         int loadsequence; // incremented each level change
2968         memexpandablearray_t array;
2969         skinframe_t *hash[SKINFRAME_HASH];
2970 }
2971 r_skinframe_t;
2972 r_skinframe_t r_skinframe;
2973
2974 void R_SkinFrame_PrepareForPurge(void)
2975 {
2976         r_skinframe.loadsequence++;
2977         // wrap it without hitting zero
2978         if (r_skinframe.loadsequence >= 200)
2979                 r_skinframe.loadsequence = 1;
2980 }
2981
2982 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2983 {
2984         if (!skinframe)
2985                 return;
2986         // mark the skinframe as used for the purging code
2987         skinframe->loadsequence = r_skinframe.loadsequence;
2988 }
2989
2990 void R_SkinFrame_Purge(void)
2991 {
2992         int i;
2993         skinframe_t *s;
2994         for (i = 0;i < SKINFRAME_HASH;i++)
2995         {
2996                 for (s = r_skinframe.hash[i];s;s = s->next)
2997                 {
2998                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2999                         {
3000                                 if (s->merged == s->base)
3001                                         s->merged = NULL;
3002                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3003                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3004                                 R_PurgeTexture(s->merged);s->merged = NULL;
3005                                 R_PurgeTexture(s->base  );s->base   = NULL;
3006                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3007                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3008                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3009                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3010                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3011                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3012                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3013                                 s->loadsequence = 0;
3014                         }
3015                 }
3016         }
3017 }
3018
3019 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3020         skinframe_t *item;
3021         char basename[MAX_QPATH];
3022
3023         Image_StripImageExtension(name, basename, sizeof(basename));
3024
3025         if( last == NULL ) {
3026                 int hashindex;
3027                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3028                 item = r_skinframe.hash[hashindex];
3029         } else {
3030                 item = last->next;
3031         }
3032
3033         // linearly search through the hash bucket
3034         for( ; item ; item = item->next ) {
3035                 if( !strcmp( item->basename, basename ) ) {
3036                         return item;
3037                 }
3038         }
3039         return NULL;
3040 }
3041
3042 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3043 {
3044         skinframe_t *item;
3045         int hashindex;
3046         char basename[MAX_QPATH];
3047
3048         Image_StripImageExtension(name, basename, sizeof(basename));
3049
3050         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3051         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3052                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3053                         break;
3054
3055         if (!item) {
3056                 rtexture_t *dyntexture;
3057                 // check whether its a dynamic texture
3058                 dyntexture = CL_GetDynTexture( basename );
3059                 if (!add && !dyntexture)
3060                         return NULL;
3061                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3062                 memset(item, 0, sizeof(*item));
3063                 strlcpy(item->basename, basename, sizeof(item->basename));
3064                 item->base = dyntexture; // either NULL or dyntexture handle
3065                 item->textureflags = textureflags;
3066                 item->comparewidth = comparewidth;
3067                 item->compareheight = compareheight;
3068                 item->comparecrc = comparecrc;
3069                 item->next = r_skinframe.hash[hashindex];
3070                 r_skinframe.hash[hashindex] = item;
3071         }
3072         else if( item->base == NULL )
3073         {
3074                 rtexture_t *dyntexture;
3075                 // check whether its a dynamic texture
3076                 // 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]
3077                 dyntexture = CL_GetDynTexture( basename );
3078                 item->base = dyntexture; // either NULL or dyntexture handle
3079         }
3080
3081         R_SkinFrame_MarkUsed(item);
3082         return item;
3083 }
3084
3085 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3086         { \
3087                 unsigned long long avgcolor[5], wsum; \
3088                 int pix, comp, w; \
3089                 avgcolor[0] = 0; \
3090                 avgcolor[1] = 0; \
3091                 avgcolor[2] = 0; \
3092                 avgcolor[3] = 0; \
3093                 avgcolor[4] = 0; \
3094                 wsum = 0; \
3095                 for(pix = 0; pix < cnt; ++pix) \
3096                 { \
3097                         w = 0; \
3098                         for(comp = 0; comp < 3; ++comp) \
3099                                 w += getpixel; \
3100                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3101                         { \
3102                                 ++wsum; \
3103                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3104                                 w = getpixel; \
3105                                 for(comp = 0; comp < 3; ++comp) \
3106                                         avgcolor[comp] += getpixel * w; \
3107                                 avgcolor[3] += w; \
3108                         } \
3109                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3110                         avgcolor[4] += getpixel; \
3111                 } \
3112                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3113                         avgcolor[3] = 1; \
3114                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3115                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3116                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3117                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3118         }
3119
3120 extern cvar_t gl_picmip;
3121 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3122 {
3123         int j;
3124         unsigned char *pixels;
3125         unsigned char *bumppixels;
3126         unsigned char *basepixels = NULL;
3127         int basepixels_width = 0;
3128         int basepixels_height = 0;
3129         skinframe_t *skinframe;
3130         rtexture_t *ddsbase = NULL;
3131         qboolean ddshasalpha = false;
3132         float ddsavgcolor[4];
3133         char basename[MAX_QPATH];
3134         int miplevel = R_PicmipForFlags(textureflags);
3135         int savemiplevel = miplevel;
3136         int mymiplevel;
3137
3138         if (cls.state == ca_dedicated)
3139                 return NULL;
3140
3141         // return an existing skinframe if already loaded
3142         // if loading of the first image fails, don't make a new skinframe as it
3143         // would cause all future lookups of this to be missing
3144         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3145         if (skinframe && skinframe->base)
3146                 return skinframe;
3147
3148         Image_StripImageExtension(name, basename, sizeof(basename));
3149
3150         // check for DDS texture file first
3151         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3152         {
3153                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3154                 if (basepixels == NULL)
3155                         return NULL;
3156         }
3157
3158         // FIXME handle miplevel
3159
3160         if (developer_loading.integer)
3161                 Con_Printf("loading skin \"%s\"\n", name);
3162
3163         // we've got some pixels to store, so really allocate this new texture now
3164         if (!skinframe)
3165                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3166         skinframe->stain = NULL;
3167         skinframe->merged = NULL;
3168         skinframe->base = NULL;
3169         skinframe->pants = NULL;
3170         skinframe->shirt = NULL;
3171         skinframe->nmap = NULL;
3172         skinframe->gloss = NULL;
3173         skinframe->glow = NULL;
3174         skinframe->fog = NULL;
3175         skinframe->reflect = NULL;
3176         skinframe->hasalpha = false;
3177
3178         if (ddsbase)
3179         {
3180                 skinframe->base = ddsbase;
3181                 skinframe->hasalpha = ddshasalpha;
3182                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3183                 if (r_loadfog && skinframe->hasalpha)
3184                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3185                 //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]);
3186         }
3187         else
3188         {
3189                 basepixels_width = image_width;
3190                 basepixels_height = image_height;
3191                 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);
3192                 if (textureflags & TEXF_ALPHA)
3193                 {
3194                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3195                         {
3196                                 if (basepixels[j] < 255)
3197                                 {
3198                                         skinframe->hasalpha = true;
3199                                         break;
3200                                 }
3201                         }
3202                         if (r_loadfog && skinframe->hasalpha)
3203                         {
3204                                 // has transparent pixels
3205                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3206                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3207                                 {
3208                                         pixels[j+0] = 255;
3209                                         pixels[j+1] = 255;
3210                                         pixels[j+2] = 255;
3211                                         pixels[j+3] = basepixels[j+3];
3212                                 }
3213                                 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);
3214                                 Mem_Free(pixels);
3215                         }
3216                 }
3217                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3218                 //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]);
3219                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3220                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3221                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3222                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3223         }
3224
3225         if (r_loaddds)
3226         {
3227                 mymiplevel = savemiplevel;
3228                 if (r_loadnormalmap)
3229                         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);
3230                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3231                 if (r_loadgloss)
3232                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3233                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3234                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3235                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3236         }
3237
3238         // _norm is the name used by tenebrae and has been adopted as standard
3239         if (r_loadnormalmap && skinframe->nmap == NULL)
3240         {
3241                 mymiplevel = savemiplevel;
3242                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3243                 {
3244                         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);
3245                         Mem_Free(pixels);
3246                         pixels = NULL;
3247                 }
3248                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3249                 {
3250                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3251                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3252                         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);
3253                         Mem_Free(pixels);
3254                         Mem_Free(bumppixels);
3255                 }
3256                 else if (r_shadow_bumpscale_basetexture.value > 0)
3257                 {
3258                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3259                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3260                         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);
3261                         Mem_Free(pixels);
3262                 }
3263                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3264                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3265         }
3266
3267         // _luma is supported only for tenebrae compatibility
3268         // _glow is the preferred name
3269         mymiplevel = savemiplevel;
3270         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))))
3271         {
3272                 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);
3273                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3274                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3275                 Mem_Free(pixels);pixels = NULL;
3276         }
3277
3278         mymiplevel = savemiplevel;
3279         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3280         {
3281                 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);
3282                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3283                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3284                 Mem_Free(pixels);
3285                 pixels = NULL;
3286         }
3287
3288         mymiplevel = savemiplevel;
3289         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3290         {
3291                 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);
3292                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3293                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3294                 Mem_Free(pixels);
3295                 pixels = NULL;
3296         }
3297
3298         mymiplevel = savemiplevel;
3299         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3300         {
3301                 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);
3302                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3303                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3304                 Mem_Free(pixels);
3305                 pixels = NULL;
3306         }
3307
3308         mymiplevel = savemiplevel;
3309         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3310         {
3311                 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);
3312                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3313                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3314                 Mem_Free(pixels);
3315                 pixels = NULL;
3316         }
3317
3318         if (basepixels)
3319                 Mem_Free(basepixels);
3320
3321         return skinframe;
3322 }
3323
3324 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3325 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3326 {
3327         int i;
3328         unsigned char *temp1, *temp2;
3329         skinframe_t *skinframe;
3330
3331         if (cls.state == ca_dedicated)
3332                 return NULL;
3333
3334         // if already loaded just return it, otherwise make a new skinframe
3335         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3336         if (skinframe && skinframe->base)
3337                 return skinframe;
3338
3339         skinframe->stain = NULL;
3340         skinframe->merged = NULL;
3341         skinframe->base = NULL;
3342         skinframe->pants = NULL;
3343         skinframe->shirt = NULL;
3344         skinframe->nmap = NULL;
3345         skinframe->gloss = NULL;
3346         skinframe->glow = NULL;
3347         skinframe->fog = NULL;
3348         skinframe->reflect = NULL;
3349         skinframe->hasalpha = false;
3350
3351         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3352         if (!skindata)
3353                 return NULL;
3354
3355         if (developer_loading.integer)
3356                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3357
3358         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3359         {
3360                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3361                 temp2 = temp1 + width * height * 4;
3362                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3363                 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);
3364                 Mem_Free(temp1);
3365         }
3366         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3367         if (textureflags & TEXF_ALPHA)
3368         {
3369                 for (i = 3;i < width * height * 4;i += 4)
3370                 {
3371                         if (skindata[i] < 255)
3372                         {
3373                                 skinframe->hasalpha = true;
3374                                 break;
3375                         }
3376                 }
3377                 if (r_loadfog && skinframe->hasalpha)
3378                 {
3379                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3380                         memcpy(fogpixels, skindata, width * height * 4);
3381                         for (i = 0;i < width * height * 4;i += 4)
3382                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3383                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3384                         Mem_Free(fogpixels);
3385                 }
3386         }
3387
3388         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3389         //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]);
3390
3391         return skinframe;
3392 }
3393
3394 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3395 {
3396         int i;
3397         int featuresmask;
3398         skinframe_t *skinframe;
3399
3400         if (cls.state == ca_dedicated)
3401                 return NULL;
3402
3403         // if already loaded just return it, otherwise make a new skinframe
3404         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3405         if (skinframe && skinframe->base)
3406                 return skinframe;
3407
3408         skinframe->stain = NULL;
3409         skinframe->merged = NULL;
3410         skinframe->base = NULL;
3411         skinframe->pants = NULL;
3412         skinframe->shirt = NULL;
3413         skinframe->nmap = NULL;
3414         skinframe->gloss = NULL;
3415         skinframe->glow = NULL;
3416         skinframe->fog = NULL;
3417         skinframe->reflect = NULL;
3418         skinframe->hasalpha = false;
3419
3420         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3421         if (!skindata)
3422                 return NULL;
3423
3424         if (developer_loading.integer)
3425                 Con_Printf("loading quake skin \"%s\"\n", name);
3426
3427         // 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)
3428         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3429         memcpy(skinframe->qpixels, skindata, width*height);
3430         skinframe->qwidth = width;
3431         skinframe->qheight = height;
3432
3433         featuresmask = 0;
3434         for (i = 0;i < width * height;i++)
3435                 featuresmask |= palette_featureflags[skindata[i]];
3436
3437         skinframe->hasalpha = false;
3438         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3439         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3440         skinframe->qgeneratemerged = true;
3441         skinframe->qgeneratebase = skinframe->qhascolormapping;
3442         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3443
3444         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3445         //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]);
3446
3447         return skinframe;
3448 }
3449
3450 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3451 {
3452         int width;
3453         int height;
3454         unsigned char *skindata;
3455
3456         if (!skinframe->qpixels)
3457                 return;
3458
3459         if (!skinframe->qhascolormapping)
3460                 colormapped = false;
3461
3462         if (colormapped)
3463         {
3464                 if (!skinframe->qgeneratebase)
3465                         return;
3466         }
3467         else
3468         {
3469                 if (!skinframe->qgeneratemerged)
3470                         return;
3471         }
3472
3473         width = skinframe->qwidth;
3474         height = skinframe->qheight;
3475         skindata = skinframe->qpixels;
3476
3477         if (skinframe->qgeneratenmap)
3478         {
3479                 unsigned char *temp1, *temp2;
3480                 skinframe->qgeneratenmap = false;
3481                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3482                 temp2 = temp1 + width * height * 4;
3483                 // use either a custom palette or the quake palette
3484                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3485                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3486                 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);
3487                 Mem_Free(temp1);
3488         }
3489
3490         if (skinframe->qgenerateglow)
3491         {
3492                 skinframe->qgenerateglow = false;
3493                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3494         }
3495
3496         if (colormapped)
3497         {
3498                 skinframe->qgeneratebase = false;
3499                 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);
3500                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3501                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3502         }
3503         else
3504         {
3505                 skinframe->qgeneratemerged = false;
3506                 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);
3507         }
3508
3509         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3510         {
3511                 Mem_Free(skinframe->qpixels);
3512                 skinframe->qpixels = NULL;
3513         }
3514 }
3515
3516 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)
3517 {
3518         int i;
3519         skinframe_t *skinframe;
3520
3521         if (cls.state == ca_dedicated)
3522                 return NULL;
3523
3524         // if already loaded just return it, otherwise make a new skinframe
3525         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3526         if (skinframe && skinframe->base)
3527                 return skinframe;
3528
3529         skinframe->stain = NULL;
3530         skinframe->merged = NULL;
3531         skinframe->base = NULL;
3532         skinframe->pants = NULL;
3533         skinframe->shirt = NULL;
3534         skinframe->nmap = NULL;
3535         skinframe->gloss = NULL;
3536         skinframe->glow = NULL;
3537         skinframe->fog = NULL;
3538         skinframe->reflect = NULL;
3539         skinframe->hasalpha = false;
3540
3541         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3542         if (!skindata)
3543                 return NULL;
3544
3545         if (developer_loading.integer)
3546                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3547
3548         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3549         if (textureflags & TEXF_ALPHA)
3550         {
3551                 for (i = 0;i < width * height;i++)
3552                 {
3553                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3554                         {
3555                                 skinframe->hasalpha = true;
3556                                 break;
3557                         }
3558                 }
3559                 if (r_loadfog && skinframe->hasalpha)
3560                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3561         }
3562
3563         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3564         //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]);
3565
3566         return skinframe;
3567 }
3568
3569 skinframe_t *R_SkinFrame_LoadMissing(void)
3570 {
3571         skinframe_t *skinframe;
3572
3573         if (cls.state == ca_dedicated)
3574                 return NULL;
3575
3576         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3577         skinframe->stain = NULL;
3578         skinframe->merged = NULL;
3579         skinframe->base = NULL;
3580         skinframe->pants = NULL;
3581         skinframe->shirt = NULL;
3582         skinframe->nmap = NULL;
3583         skinframe->gloss = NULL;
3584         skinframe->glow = NULL;
3585         skinframe->fog = NULL;
3586         skinframe->reflect = NULL;
3587         skinframe->hasalpha = false;
3588
3589         skinframe->avgcolor[0] = rand() / RAND_MAX;
3590         skinframe->avgcolor[1] = rand() / RAND_MAX;
3591         skinframe->avgcolor[2] = rand() / RAND_MAX;
3592         skinframe->avgcolor[3] = 1;
3593
3594         return skinframe;
3595 }
3596
3597 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3598 typedef struct suffixinfo_s
3599 {
3600         const char *suffix;
3601         qboolean flipx, flipy, flipdiagonal;
3602 }
3603 suffixinfo_t;
3604 static suffixinfo_t suffix[3][6] =
3605 {
3606         {
3607                 {"px",   false, false, false},
3608                 {"nx",   false, false, false},
3609                 {"py",   false, false, false},
3610                 {"ny",   false, false, false},
3611                 {"pz",   false, false, false},
3612                 {"nz",   false, false, false}
3613         },
3614         {
3615                 {"posx", false, false, false},
3616                 {"negx", false, false, false},
3617                 {"posy", false, false, false},
3618                 {"negy", false, false, false},
3619                 {"posz", false, false, false},
3620                 {"negz", false, false, false}
3621         },
3622         {
3623                 {"rt",    true, false,  true},
3624                 {"lf",   false,  true,  true},
3625                 {"ft",    true,  true, false},
3626                 {"bk",   false, false, false},
3627                 {"up",    true, false,  true},
3628                 {"dn",    true, false,  true}
3629         }
3630 };
3631
3632 static int componentorder[4] = {0, 1, 2, 3};
3633
3634 rtexture_t *R_LoadCubemap(const char *basename)
3635 {
3636         int i, j, cubemapsize;
3637         unsigned char *cubemappixels, *image_buffer;
3638         rtexture_t *cubemaptexture;
3639         char name[256];
3640         // must start 0 so the first loadimagepixels has no requested width/height
3641         cubemapsize = 0;
3642         cubemappixels = NULL;
3643         cubemaptexture = NULL;
3644         // keep trying different suffix groups (posx, px, rt) until one loads
3645         for (j = 0;j < 3 && !cubemappixels;j++)
3646         {
3647                 // load the 6 images in the suffix group
3648                 for (i = 0;i < 6;i++)
3649                 {
3650                         // generate an image name based on the base and and suffix
3651                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3652                         // load it
3653                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3654                         {
3655                                 // an image loaded, make sure width and height are equal
3656                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3657                                 {
3658                                         // if this is the first image to load successfully, allocate the cubemap memory
3659                                         if (!cubemappixels && image_width >= 1)
3660                                         {
3661                                                 cubemapsize = image_width;
3662                                                 // note this clears to black, so unavailable sides are black
3663                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3664                                         }
3665                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3666                                         if (cubemappixels)
3667                                                 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);
3668                                 }
3669                                 else
3670                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3671                                 // free the image
3672                                 Mem_Free(image_buffer);
3673                         }
3674                 }
3675         }
3676         // if a cubemap loaded, upload it
3677         if (cubemappixels)
3678         {
3679                 if (developer_loading.integer)
3680                         Con_Printf("loading cubemap \"%s\"\n", basename);
3681
3682                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3683                 Mem_Free(cubemappixels);
3684         }
3685         else
3686         {
3687                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3688                 if (developer_loading.integer)
3689                 {
3690                         Con_Printf("(tried tried images ");
3691                         for (j = 0;j < 3;j++)
3692                                 for (i = 0;i < 6;i++)
3693                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3694                         Con_Print(" and was unable to find any of them).\n");
3695                 }
3696         }
3697         return cubemaptexture;
3698 }
3699
3700 rtexture_t *R_GetCubemap(const char *basename)
3701 {
3702         int i;
3703         for (i = 0;i < r_texture_numcubemaps;i++)
3704                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3705                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3706         if (i >= MAX_CUBEMAPS)
3707                 return r_texture_whitecube;
3708         r_texture_numcubemaps++;
3709         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3710         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3711         return r_texture_cubemaps[i].texture;
3712 }
3713
3714 void R_FreeCubemaps(void)
3715 {
3716         int i;
3717         for (i = 0;i < r_texture_numcubemaps;i++)
3718         {
3719                 if (developer_loading.integer)
3720                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3721                 if (r_texture_cubemaps[i].texture)
3722                         R_FreeTexture(r_texture_cubemaps[i].texture);
3723         }
3724         r_texture_numcubemaps = 0;
3725 }
3726
3727 void R_Main_FreeViewCache(void)
3728 {
3729         if (r_refdef.viewcache.entityvisible)
3730                 Mem_Free(r_refdef.viewcache.entityvisible);
3731         if (r_refdef.viewcache.world_pvsbits)
3732                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3733         if (r_refdef.viewcache.world_leafvisible)
3734                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3735         if (r_refdef.viewcache.world_surfacevisible)
3736                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3737         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3738 }
3739
3740 void R_Main_ResizeViewCache(void)
3741 {
3742         int numentities = r_refdef.scene.numentities;
3743         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3744         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3745         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3746         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3747         if (r_refdef.viewcache.maxentities < numentities)
3748         {
3749                 r_refdef.viewcache.maxentities = numentities;
3750                 if (r_refdef.viewcache.entityvisible)
3751                         Mem_Free(r_refdef.viewcache.entityvisible);
3752                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3753         }
3754         if (r_refdef.viewcache.world_numclusters != numclusters)
3755         {
3756                 r_refdef.viewcache.world_numclusters = numclusters;
3757                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3758                 if (r_refdef.viewcache.world_pvsbits)
3759                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3760                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3761         }
3762         if (r_refdef.viewcache.world_numleafs != numleafs)
3763         {
3764                 r_refdef.viewcache.world_numleafs = numleafs;
3765                 if (r_refdef.viewcache.world_leafvisible)
3766                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3767                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3768         }
3769         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3770         {
3771                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3772                 if (r_refdef.viewcache.world_surfacevisible)
3773                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3774                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3775         }
3776 }
3777
3778 extern rtexture_t *loadingscreentexture;
3779 void gl_main_start(void)
3780 {
3781         loadingscreentexture = NULL;
3782         r_texture_blanknormalmap = NULL;
3783         r_texture_white = NULL;
3784         r_texture_grey128 = NULL;
3785         r_texture_black = NULL;
3786         r_texture_whitecube = NULL;
3787         r_texture_normalizationcube = NULL;
3788         r_texture_fogattenuation = NULL;
3789         r_texture_fogheighttexture = NULL;
3790         r_texture_gammaramps = NULL;
3791         r_texture_numcubemaps = 0;
3792
3793         r_loaddds = r_texture_dds_load.integer != 0;
3794         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3795
3796         switch(vid.renderpath)
3797         {
3798         case RENDERPATH_GL20:
3799         case RENDERPATH_D3D9:
3800         case RENDERPATH_D3D10:
3801         case RENDERPATH_D3D11:
3802         case RENDERPATH_SOFT:
3803                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3804                 Cvar_SetValueQuick(&gl_combine, 1);
3805                 Cvar_SetValueQuick(&r_glsl, 1);
3806                 r_loadnormalmap = true;
3807                 r_loadgloss = true;
3808                 r_loadfog = false;
3809                 break;
3810         case RENDERPATH_GL13:
3811                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3812                 Cvar_SetValueQuick(&gl_combine, 1);
3813                 Cvar_SetValueQuick(&r_glsl, 0);
3814                 r_loadnormalmap = false;
3815                 r_loadgloss = false;
3816                 r_loadfog = true;
3817                 break;
3818         case RENDERPATH_GL11:
3819                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3820                 Cvar_SetValueQuick(&gl_combine, 0);
3821                 Cvar_SetValueQuick(&r_glsl, 0);
3822                 r_loadnormalmap = false;
3823                 r_loadgloss = false;
3824                 r_loadfog = true;
3825                 break;
3826         case RENDERPATH_GLES2:
3827                 Cvar_SetValueQuick(&r_textureunits, 1);
3828                 Cvar_SetValueQuick(&gl_combine, 1);
3829                 Cvar_SetValueQuick(&r_glsl, 1);
3830                 r_loadnormalmap = true;
3831                 r_loadgloss = false;
3832                 r_loadfog = false;
3833                 break;
3834         }
3835
3836         R_AnimCache_Free();
3837         R_FrameData_Reset();
3838
3839         r_numqueries = 0;
3840         r_maxqueries = 0;
3841         memset(r_queries, 0, sizeof(r_queries));
3842
3843         r_qwskincache = NULL;
3844         r_qwskincache_size = 0;
3845
3846         // set up r_skinframe loading system for textures
3847         memset(&r_skinframe, 0, sizeof(r_skinframe));
3848         r_skinframe.loadsequence = 1;
3849         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3850
3851         r_main_texturepool = R_AllocTexturePool();
3852         R_BuildBlankTextures();
3853         R_BuildNoTexture();
3854         if (vid.support.arb_texture_cube_map)
3855         {
3856                 R_BuildWhiteCube();
3857                 R_BuildNormalizationCube();
3858         }
3859         r_texture_fogattenuation = NULL;
3860         r_texture_fogheighttexture = NULL;
3861         r_texture_gammaramps = NULL;
3862         //r_texture_fogintensity = NULL;
3863         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3864         memset(&r_waterstate, 0, sizeof(r_waterstate));
3865         r_glsl_permutation = NULL;
3866         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3867         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3868         glslshaderstring = NULL;
3869 #ifdef SUPPORTD3D
3870         r_hlsl_permutation = NULL;
3871         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3872         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3873 #endif
3874         hlslshaderstring = NULL;
3875         memset(&r_svbsp, 0, sizeof (r_svbsp));
3876
3877         r_refdef.fogmasktable_density = 0;
3878 }
3879
3880 void gl_main_shutdown(void)
3881 {
3882         R_AnimCache_Free();
3883         R_FrameData_Reset();
3884
3885         R_Main_FreeViewCache();
3886
3887         switch(vid.renderpath)
3888         {
3889         case RENDERPATH_GL11:
3890         case RENDERPATH_GL13:
3891         case RENDERPATH_GL20:
3892         case RENDERPATH_GLES2:
3893                 if (r_maxqueries)
3894                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3895                 break;
3896         case RENDERPATH_D3D9:
3897                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3898                 break;
3899         case RENDERPATH_D3D10:
3900                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3901                 break;
3902         case RENDERPATH_D3D11:
3903                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3904                 break;
3905         case RENDERPATH_SOFT:
3906                 break;
3907         }
3908
3909         r_numqueries = 0;
3910         r_maxqueries = 0;
3911         memset(r_queries, 0, sizeof(r_queries));
3912
3913         r_qwskincache = NULL;
3914         r_qwskincache_size = 0;
3915
3916         // clear out the r_skinframe state
3917         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3918         memset(&r_skinframe, 0, sizeof(r_skinframe));
3919
3920         if (r_svbsp.nodes)
3921                 Mem_Free(r_svbsp.nodes);
3922         memset(&r_svbsp, 0, sizeof (r_svbsp));
3923         R_FreeTexturePool(&r_main_texturepool);
3924         loadingscreentexture = NULL;
3925         r_texture_blanknormalmap = NULL;
3926         r_texture_white = NULL;
3927         r_texture_grey128 = NULL;
3928         r_texture_black = NULL;
3929         r_texture_whitecube = NULL;
3930         r_texture_normalizationcube = NULL;
3931         r_texture_fogattenuation = NULL;
3932         r_texture_fogheighttexture = NULL;
3933         r_texture_gammaramps = NULL;
3934         r_texture_numcubemaps = 0;
3935         //r_texture_fogintensity = NULL;
3936         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3937         memset(&r_waterstate, 0, sizeof(r_waterstate));
3938         R_GLSL_Restart_f();
3939
3940         r_glsl_permutation = NULL;
3941         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3942         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3943         glslshaderstring = NULL;
3944 #ifdef SUPPORTD3D
3945         r_hlsl_permutation = NULL;
3946         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3947         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3948 #endif
3949         hlslshaderstring = NULL;
3950 }
3951
3952 extern void CL_ParseEntityLump(char *entitystring);
3953 void gl_main_newmap(void)
3954 {
3955         // FIXME: move this code to client
3956         char *entities, entname[MAX_QPATH];
3957         if (r_qwskincache)
3958                 Mem_Free(r_qwskincache);
3959         r_qwskincache = NULL;
3960         r_qwskincache_size = 0;
3961         if (cl.worldmodel)
3962         {
3963                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3964                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3965                 {
3966                         CL_ParseEntityLump(entities);
3967                         Mem_Free(entities);
3968                         return;
3969                 }
3970                 if (cl.worldmodel->brush.entities)
3971                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3972         }
3973         R_Main_FreeViewCache();
3974
3975         R_FrameData_Reset();
3976 }
3977
3978 void GL_Main_Init(void)
3979 {
3980         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3981
3982         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3983         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3984         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3985         if (gamemode == GAME_NEHAHRA)
3986         {
3987                 Cvar_RegisterVariable (&gl_fogenable);
3988                 Cvar_RegisterVariable (&gl_fogdensity);
3989                 Cvar_RegisterVariable (&gl_fogred);
3990                 Cvar_RegisterVariable (&gl_foggreen);
3991                 Cvar_RegisterVariable (&gl_fogblue);
3992                 Cvar_RegisterVariable (&gl_fogstart);
3993                 Cvar_RegisterVariable (&gl_fogend);
3994                 Cvar_RegisterVariable (&gl_skyclip);
3995         }
3996         Cvar_RegisterVariable(&r_motionblur);
3997         Cvar_RegisterVariable(&r_motionblur_maxblur);
3998         Cvar_RegisterVariable(&r_motionblur_bmin);
3999         Cvar_RegisterVariable(&r_motionblur_vmin);
4000         Cvar_RegisterVariable(&r_motionblur_vmax);
4001         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4002         Cvar_RegisterVariable(&r_motionblur_randomize);
4003         Cvar_RegisterVariable(&r_damageblur);
4004         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4005         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4006         Cvar_RegisterVariable(&r_equalize_entities_by);
4007         Cvar_RegisterVariable(&r_equalize_entities_to);
4008         Cvar_RegisterVariable(&r_depthfirst);
4009         Cvar_RegisterVariable(&r_useinfinitefarclip);
4010         Cvar_RegisterVariable(&r_farclip_base);
4011         Cvar_RegisterVariable(&r_farclip_world);
4012         Cvar_RegisterVariable(&r_nearclip);
4013         Cvar_RegisterVariable(&r_showbboxes);
4014         Cvar_RegisterVariable(&r_showsurfaces);
4015         Cvar_RegisterVariable(&r_showtris);
4016         Cvar_RegisterVariable(&r_shownormals);
4017         Cvar_RegisterVariable(&r_showlighting);
4018         Cvar_RegisterVariable(&r_showshadowvolumes);
4019         Cvar_RegisterVariable(&r_showcollisionbrushes);
4020         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4021         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4022         Cvar_RegisterVariable(&r_showdisabledepthtest);
4023         Cvar_RegisterVariable(&r_drawportals);
4024         Cvar_RegisterVariable(&r_drawentities);
4025         Cvar_RegisterVariable(&r_draw2d);
4026         Cvar_RegisterVariable(&r_drawworld);
4027         Cvar_RegisterVariable(&r_cullentities_trace);
4028         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4029         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4030         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4031         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4032         Cvar_RegisterVariable(&r_drawviewmodel);
4033         Cvar_RegisterVariable(&r_drawexteriormodel);
4034         Cvar_RegisterVariable(&r_speeds);
4035         Cvar_RegisterVariable(&r_fullbrights);
4036         Cvar_RegisterVariable(&r_wateralpha);
4037         Cvar_RegisterVariable(&r_dynamic);
4038         Cvar_RegisterVariable(&r_fakelight);
4039         Cvar_RegisterVariable(&r_fakelight_intensity);
4040         Cvar_RegisterVariable(&r_fullbright);
4041         Cvar_RegisterVariable(&r_shadows);
4042         Cvar_RegisterVariable(&r_shadows_darken);
4043         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4044         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4045         Cvar_RegisterVariable(&r_shadows_throwdistance);
4046         Cvar_RegisterVariable(&r_shadows_throwdirection);
4047         Cvar_RegisterVariable(&r_shadows_focus);
4048         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4049         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4050         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4051         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4052         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4053         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4054         Cvar_RegisterVariable(&r_fog_exp2);
4055         Cvar_RegisterVariable(&r_drawfog);
4056         Cvar_RegisterVariable(&r_transparentdepthmasking);
4057         Cvar_RegisterVariable(&r_texture_dds_load);
4058         Cvar_RegisterVariable(&r_texture_dds_save);
4059         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4060         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4061         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4062         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4063         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4064         Cvar_RegisterVariable(&r_textureunits);
4065         Cvar_RegisterVariable(&gl_combine);
4066         Cvar_RegisterVariable(&r_glsl);
4067         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4068         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4069         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4070         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4071         Cvar_RegisterVariable(&r_glsl_postprocess);
4072         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4073         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4074         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4075         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4076         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4077         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4078         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4079         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4080
4081         Cvar_RegisterVariable(&r_water);
4082         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4083         Cvar_RegisterVariable(&r_water_clippingplanebias);
4084         Cvar_RegisterVariable(&r_water_refractdistort);
4085         Cvar_RegisterVariable(&r_water_reflectdistort);
4086         Cvar_RegisterVariable(&r_water_scissormode);
4087         Cvar_RegisterVariable(&r_lerpsprites);
4088         Cvar_RegisterVariable(&r_lerpmodels);
4089         Cvar_RegisterVariable(&r_lerplightstyles);
4090         Cvar_RegisterVariable(&r_waterscroll);
4091         Cvar_RegisterVariable(&r_bloom);
4092         Cvar_RegisterVariable(&r_bloom_colorscale);
4093         Cvar_RegisterVariable(&r_bloom_brighten);
4094         Cvar_RegisterVariable(&r_bloom_blur);
4095         Cvar_RegisterVariable(&r_bloom_resolution);
4096         Cvar_RegisterVariable(&r_bloom_colorexponent);
4097         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4098         Cvar_RegisterVariable(&r_hdr);
4099         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4100         Cvar_RegisterVariable(&r_hdr_glowintensity);
4101         Cvar_RegisterVariable(&r_hdr_range);
4102         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4103         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4104         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4105         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4106         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4107         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4108         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4109         Cvar_RegisterVariable(&developer_texturelogging);
4110         Cvar_RegisterVariable(&gl_lightmaps);
4111         Cvar_RegisterVariable(&r_test);
4112         Cvar_RegisterVariable(&r_glsl_saturation);
4113         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4114         Cvar_RegisterVariable(&r_framedatasize);
4115         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4116                 Cvar_SetValue("r_fullbrights", 0);
4117         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4118
4119         Cvar_RegisterVariable(&r_track_sprites);
4120         Cvar_RegisterVariable(&r_track_sprites_flags);
4121         Cvar_RegisterVariable(&r_track_sprites_scalew);
4122         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4123         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4124         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4125         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4126         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4127 }
4128
4129 extern void R_Textures_Init(void);
4130 extern void GL_Draw_Init(void);
4131 extern void GL_Main_Init(void);
4132 extern void R_Shadow_Init(void);
4133 extern void R_Sky_Init(void);
4134 extern void GL_Surf_Init(void);
4135 extern void R_Particles_Init(void);
4136 extern void R_Explosion_Init(void);
4137 extern void gl_backend_init(void);
4138 extern void Sbar_Init(void);
4139 extern void R_LightningBeams_Init(void);
4140 extern void Mod_RenderInit(void);
4141 extern void Font_Init(void);
4142
4143 void Render_Init(void)
4144 {
4145         gl_backend_init();
4146         R_Textures_Init();
4147         GL_Main_Init();
4148         Font_Init();
4149         GL_Draw_Init();
4150         R_Shadow_Init();
4151         R_Sky_Init();
4152         GL_Surf_Init();
4153         Sbar_Init();
4154         R_Particles_Init();
4155         R_Explosion_Init();
4156         R_LightningBeams_Init();
4157         Mod_RenderInit();
4158 }
4159
4160 /*
4161 ===============
4162 GL_Init
4163 ===============
4164 */
4165 extern char *ENGINE_EXTENSIONS;
4166 void GL_Init (void)
4167 {
4168         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4169         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4170         gl_version = (const char *)qglGetString(GL_VERSION);
4171         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4172
4173         if (!gl_extensions)
4174                 gl_extensions = "";
4175         if (!gl_platformextensions)
4176                 gl_platformextensions = "";
4177
4178         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4179         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4180         Con_Printf("GL_VERSION: %s\n", gl_version);
4181         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4182         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4183
4184         VID_CheckExtensions();
4185
4186         // LordHavoc: report supported extensions
4187         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4188
4189         // clear to black (loading plaque will be seen over this)
4190         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4191 }
4192
4193 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4194 {
4195         int i;
4196         mplane_t *p;
4197         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4198         {
4199                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4200                 if (i == 4)
4201                         continue;
4202                 p = r_refdef.view.frustum + i;
4203                 switch(p->signbits)
4204                 {
4205                 default:
4206                 case 0:
4207                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4208                                 return true;
4209                         break;
4210                 case 1:
4211                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4212                                 return true;
4213                         break;
4214                 case 2:
4215                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4216                                 return true;
4217                         break;
4218                 case 3:
4219                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4220                                 return true;
4221                         break;
4222                 case 4:
4223                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4224                                 return true;
4225                         break;
4226                 case 5:
4227                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4228                                 return true;
4229                         break;
4230                 case 6:
4231                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4232                                 return true;
4233                         break;
4234                 case 7:
4235                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4236                                 return true;
4237                         break;
4238                 }
4239         }
4240         return false;
4241 }
4242
4243 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4244 {
4245         int i;
4246         const mplane_t *p;
4247         for (i = 0;i < numplanes;i++)
4248         {
4249                 p = planes + i;
4250                 switch(p->signbits)
4251                 {
4252                 default:
4253                 case 0:
4254                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4255                                 return true;
4256                         break;
4257                 case 1:
4258                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4259                                 return true;
4260                         break;
4261                 case 2:
4262                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4263                                 return true;
4264                         break;
4265                 case 3:
4266                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4267                                 return true;
4268                         break;
4269                 case 4:
4270                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4271                                 return true;
4272                         break;
4273                 case 5:
4274                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4275                                 return true;
4276                         break;
4277                 case 6:
4278                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4279                                 return true;
4280                         break;
4281                 case 7:
4282                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4283                                 return true;
4284                         break;
4285                 }
4286         }
4287         return false;
4288 }
4289
4290 //==================================================================================
4291
4292 // LordHavoc: this stores temporary data used within the same frame
4293
4294 typedef struct r_framedata_mem_s
4295 {
4296         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4297         size_t size; // how much usable space
4298         size_t current; // how much space in use
4299         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4300         size_t wantedsize; // how much space was allocated
4301         unsigned char *data; // start of real data (16byte aligned)
4302 }
4303 r_framedata_mem_t;
4304
4305 static r_framedata_mem_t *r_framedata_mem;
4306
4307 void R_FrameData_Reset(void)
4308 {
4309         while (r_framedata_mem)
4310         {
4311                 r_framedata_mem_t *next = r_framedata_mem->purge;
4312                 Mem_Free(r_framedata_mem);
4313                 r_framedata_mem = next;
4314         }
4315 }
4316
4317 void R_FrameData_Resize(void)
4318 {
4319         size_t wantedsize;
4320         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4321         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4322         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4323         {
4324                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4325                 newmem->wantedsize = wantedsize;
4326                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4327                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4328                 newmem->current = 0;
4329                 newmem->mark = 0;
4330                 newmem->purge = r_framedata_mem;
4331                 r_framedata_mem = newmem;
4332         }
4333 }
4334
4335 void R_FrameData_NewFrame(void)
4336 {
4337         R_FrameData_Resize();
4338         if (!r_framedata_mem)
4339                 return;
4340         // if we ran out of space on the last frame, free the old memory now
4341         while (r_framedata_mem->purge)
4342         {
4343                 // repeatedly remove the second item in the list, leaving only head
4344                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4345                 Mem_Free(r_framedata_mem->purge);
4346                 r_framedata_mem->purge = next;
4347         }
4348         // reset the current mem pointer
4349         r_framedata_mem->current = 0;
4350         r_framedata_mem->mark = 0;
4351 }
4352
4353 void *R_FrameData_Alloc(size_t size)
4354 {
4355         void *data;
4356
4357         // align to 16 byte boundary - the data pointer is already aligned, so we
4358         // only need to ensure the size of every allocation is also aligned
4359         size = (size + 15) & ~15;
4360
4361         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4362         {
4363                 // emergency - we ran out of space, allocate more memory
4364                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4365                 R_FrameData_Resize();
4366         }
4367
4368         data = r_framedata_mem->data + r_framedata_mem->current;
4369         r_framedata_mem->current += size;
4370
4371         // count the usage for stats
4372         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4373         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4374
4375         return (void *)data;
4376 }
4377
4378 void *R_FrameData_Store(size_t size, void *data)
4379 {
4380         void *d = R_FrameData_Alloc(size);
4381         if (d && data)
4382                 memcpy(d, data, size);
4383         return d;
4384 }
4385
4386 void R_FrameData_SetMark(void)
4387 {
4388         if (!r_framedata_mem)
4389                 return;
4390         r_framedata_mem->mark = r_framedata_mem->current;
4391 }
4392
4393 void R_FrameData_ReturnToMark(void)
4394 {
4395         if (!r_framedata_mem)
4396                 return;
4397         r_framedata_mem->current = r_framedata_mem->mark;
4398 }
4399
4400 //==================================================================================
4401
4402 // LordHavoc: animcache originally written by Echon, rewritten since then
4403
4404 /**
4405  * Animation cache prevents re-generating mesh data for an animated model
4406  * multiple times in one frame for lighting, shadowing, reflections, etc.
4407  */
4408
4409 void R_AnimCache_Free(void)
4410 {
4411 }
4412
4413 void R_AnimCache_ClearCache(void)
4414 {
4415         int i;
4416         entity_render_t *ent;
4417
4418         for (i = 0;i < r_refdef.scene.numentities;i++)
4419         {
4420                 ent = r_refdef.scene.entities[i];
4421                 ent->animcache_vertex3f = NULL;
4422                 ent->animcache_normal3f = NULL;
4423                 ent->animcache_svector3f = NULL;
4424                 ent->animcache_tvector3f = NULL;
4425                 ent->animcache_vertexmesh = NULL;
4426                 ent->animcache_vertex3fbuffer = NULL;
4427                 ent->animcache_vertexmeshbuffer = NULL;
4428         }
4429 }
4430
4431 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4432 {
4433         int i;
4434
4435         // check if we need the meshbuffers
4436         if (!vid.useinterleavedarrays)
4437                 return;
4438
4439         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4440                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4441         // TODO: upload vertex3f buffer?
4442         if (ent->animcache_vertexmesh)
4443         {
4444                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4445                 for (i = 0;i < numvertices;i++)
4446                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4447                 if (ent->animcache_svector3f)
4448                         for (i = 0;i < numvertices;i++)
4449                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4450                 if (ent->animcache_tvector3f)
4451                         for (i = 0;i < numvertices;i++)
4452                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4453                 if (ent->animcache_normal3f)
4454                         for (i = 0;i < numvertices;i++)
4455                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4456                 // TODO: upload vertexmeshbuffer?
4457         }
4458 }
4459
4460 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4461 {
4462         dp_model_t *model = ent->model;
4463         int numvertices;
4464         // see if it's already cached this frame
4465         if (ent->animcache_vertex3f)
4466         {
4467                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4468                 if (wantnormals || wanttangents)
4469                 {
4470                         if (ent->animcache_normal3f)
4471                                 wantnormals = false;
4472                         if (ent->animcache_svector3f)
4473                                 wanttangents = false;
4474                         if (wantnormals || wanttangents)
4475                         {
4476                                 numvertices = model->surfmesh.num_vertices;
4477                                 if (wantnormals)
4478                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4479                                 if (wanttangents)
4480                                 {
4481                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4482                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4483                                 }
4484                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4485                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4486                         }
4487                 }
4488         }
4489         else
4490         {
4491                 // see if this ent is worth caching
4492                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4493                         return false;
4494                 // get some memory for this entity and generate mesh data
4495                 numvertices = model->surfmesh.num_vertices;
4496                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4497                 if (wantnormals)
4498                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4499                 if (wanttangents)
4500                 {
4501                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4502                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4503                 }
4504                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4505                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4506         }
4507         return true;
4508 }
4509
4510 void R_AnimCache_CacheVisibleEntities(void)
4511 {
4512         int i;
4513         qboolean wantnormals = true;
4514         qboolean wanttangents = !r_showsurfaces.integer;
4515
4516         switch(vid.renderpath)
4517         {
4518         case RENDERPATH_GL20:
4519         case RENDERPATH_D3D9:
4520         case RENDERPATH_D3D10:
4521         case RENDERPATH_D3D11:
4522         case RENDERPATH_GLES2:
4523                 break;
4524         case RENDERPATH_GL13:
4525         case RENDERPATH_GL11:
4526                 wanttangents = false;
4527                 break;
4528         case RENDERPATH_SOFT:
4529                 break;
4530         }
4531
4532         if (r_shownormals.integer)
4533                 wanttangents = wantnormals = true;
4534
4535         // TODO: thread this
4536         // NOTE: R_PrepareRTLights() also caches entities
4537
4538         for (i = 0;i < r_refdef.scene.numentities;i++)
4539                 if (r_refdef.viewcache.entityvisible[i])
4540                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4541 }
4542
4543 //==================================================================================
4544
4545 static void R_View_UpdateEntityLighting (void)
4546 {
4547         int i;
4548         entity_render_t *ent;
4549         vec3_t tempdiffusenormal, avg;
4550         vec_t f, fa, fd, fdd;
4551         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4552
4553         for (i = 0;i < r_refdef.scene.numentities;i++)
4554         {
4555                 ent = r_refdef.scene.entities[i];
4556
4557                 // skip unseen models
4558                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4559                         continue;
4560
4561                 // skip bsp models
4562                 if (ent->model && ent->model->brush.num_leafs)
4563                 {
4564                         // TODO: use modellight for r_ambient settings on world?
4565                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4566                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4567                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4568                         continue;
4569                 }
4570
4571                 // fetch the lighting from the worldmodel data
4572                 VectorClear(ent->modellight_ambient);
4573                 VectorClear(ent->modellight_diffuse);
4574                 VectorClear(tempdiffusenormal);
4575                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4576                 {
4577                         vec3_t org;
4578                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4579
4580                         // complete lightning for lit sprites
4581                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4582                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4583                         {
4584                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4585                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4586                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4587                         }
4588                         else
4589                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4590
4591                         if(ent->flags & RENDER_EQUALIZE)
4592                         {
4593                                 // first fix up ambient lighting...
4594                                 if(r_equalize_entities_minambient.value > 0)
4595                                 {
4596                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4597                                         if(fd > 0)
4598                                         {
4599                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4600                                                 if(fa < r_equalize_entities_minambient.value * fd)
4601                                                 {
4602                                                         // solve:
4603                                                         //   fa'/fd' = minambient
4604                                                         //   fa'+0.25*fd' = fa+0.25*fd
4605                                                         //   ...
4606                                                         //   fa' = fd' * minambient
4607                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4608                                                         //   ...
4609                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4610                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4611                                                         //   ...
4612                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4613                                                         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
4614                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4615                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4616                                                 }
4617                                         }
4618                                 }
4619
4620                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4621                                 {
4622                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4623                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4624                                         f = fa + 0.25 * fd;
4625                                         if(f > 0)
4626                                         {
4627                                                 // adjust brightness and saturation to target
4628                                                 avg[0] = avg[1] = avg[2] = fa / f;
4629                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4630                                                 avg[0] = avg[1] = avg[2] = fd / f;
4631                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4632                                         }
4633                                 }
4634                         }
4635                 }
4636                 else // highly rare
4637                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4638
4639                 // move the light direction into modelspace coordinates for lighting code
4640                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4641                 if(VectorLength2(ent->modellight_lightdir) == 0)
4642                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4643                 VectorNormalize(ent->modellight_lightdir);
4644         }
4645 }
4646
4647 #define MAX_LINEOFSIGHTTRACES 64
4648
4649 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4650 {
4651         int i;
4652         vec3_t boxmins, boxmaxs;
4653         vec3_t start;
4654         vec3_t end;
4655         dp_model_t *model = r_refdef.scene.worldmodel;
4656
4657         if (!model || !model->brush.TraceLineOfSight)
4658                 return true;
4659
4660         // expand the box a little
4661         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4662         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4663         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4664         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4665         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4666         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4667
4668         // return true if eye is inside enlarged box
4669         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4670                 return true;
4671
4672         // try center
4673         VectorCopy(eye, start);
4674         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4675         if (model->brush.TraceLineOfSight(model, start, end))
4676                 return true;
4677
4678         // try various random positions
4679         for (i = 0;i < numsamples;i++)
4680         {
4681                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4682                 if (model->brush.TraceLineOfSight(model, start, end))
4683                         return true;
4684         }
4685
4686         return false;
4687 }
4688
4689
4690 static void R_View_UpdateEntityVisible (void)
4691 {
4692         int i;
4693         int renderimask;
4694         int samples;
4695         entity_render_t *ent;
4696
4697         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4698                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4699                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4700                 :                                                          RENDER_EXTERIORMODEL;
4701         if (!r_drawviewmodel.integer)
4702                 renderimask |= RENDER_VIEWMODEL;
4703         if (!r_drawexteriormodel.integer)
4704                 renderimask |= RENDER_EXTERIORMODEL;
4705         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4706         {
4707                 // worldmodel can check visibility
4708                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4709                 for (i = 0;i < r_refdef.scene.numentities;i++)
4710                 {
4711                         ent = r_refdef.scene.entities[i];
4712                         if (!(ent->flags & renderimask))
4713                         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)))
4714                         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))
4715                                 r_refdef.viewcache.entityvisible[i] = true;
4716                 }
4717                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4718                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4719                 {
4720                         for (i = 0;i < r_refdef.scene.numentities;i++)
4721                         {
4722                                 ent = r_refdef.scene.entities[i];
4723                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4724                                 {
4725                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4726                                         if (samples < 0)
4727                                                 continue; // temp entities do pvs only
4728                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4729                                                 ent->last_trace_visibility = realtime;
4730                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4731                                                 r_refdef.viewcache.entityvisible[i] = 0;
4732                                 }
4733                         }
4734                 }
4735         }
4736         else
4737         {
4738                 // no worldmodel or it can't check visibility
4739                 for (i = 0;i < r_refdef.scene.numentities;i++)
4740                 {
4741                         ent = r_refdef.scene.entities[i];
4742                         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));
4743                 }
4744         }
4745 }
4746
4747 /// only used if skyrendermasked, and normally returns false
4748 int R_DrawBrushModelsSky (void)
4749 {
4750         int i, sky;
4751         entity_render_t *ent;
4752
4753         sky = false;
4754         for (i = 0;i < r_refdef.scene.numentities;i++)
4755         {
4756                 if (!r_refdef.viewcache.entityvisible[i])
4757                         continue;
4758                 ent = r_refdef.scene.entities[i];
4759                 if (!ent->model || !ent->model->DrawSky)
4760                         continue;
4761                 ent->model->DrawSky(ent);
4762                 sky = true;
4763         }
4764         return sky;
4765 }
4766
4767 static void R_DrawNoModel(entity_render_t *ent);
4768 static void R_DrawModels(void)
4769 {
4770         int i;
4771         entity_render_t *ent;
4772
4773         for (i = 0;i < r_refdef.scene.numentities;i++)
4774         {
4775                 if (!r_refdef.viewcache.entityvisible[i])
4776                         continue;
4777                 ent = r_refdef.scene.entities[i];
4778                 r_refdef.stats.entities++;
4779                 if (ent->model && ent->model->Draw != NULL)
4780                         ent->model->Draw(ent);
4781                 else
4782                         R_DrawNoModel(ent);
4783         }
4784 }
4785
4786 static void R_DrawModelsDepth(void)
4787 {
4788         int i;
4789         entity_render_t *ent;
4790
4791         for (i = 0;i < r_refdef.scene.numentities;i++)
4792         {
4793                 if (!r_refdef.viewcache.entityvisible[i])
4794                         continue;
4795                 ent = r_refdef.scene.entities[i];
4796                 if (ent->model && ent->model->DrawDepth != NULL)
4797                         ent->model->DrawDepth(ent);
4798         }
4799 }
4800
4801 static void R_DrawModelsDebug(void)
4802 {
4803         int i;
4804         entity_render_t *ent;
4805
4806         for (i = 0;i < r_refdef.scene.numentities;i++)
4807         {
4808                 if (!r_refdef.viewcache.entityvisible[i])
4809                         continue;
4810                 ent = r_refdef.scene.entities[i];
4811                 if (ent->model && ent->model->DrawDebug != NULL)
4812                         ent->model->DrawDebug(ent);
4813         }
4814 }
4815
4816 static void R_DrawModelsAddWaterPlanes(void)
4817 {
4818         int i;
4819         entity_render_t *ent;
4820
4821         for (i = 0;i < r_refdef.scene.numentities;i++)
4822         {
4823                 if (!r_refdef.viewcache.entityvisible[i])
4824                         continue;
4825                 ent = r_refdef.scene.entities[i];
4826                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4827                         ent->model->DrawAddWaterPlanes(ent);
4828         }
4829 }
4830
4831 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4832 {
4833         if (r_hdr_irisadaptation.integer)
4834         {
4835                 vec3_t ambient;
4836                 vec3_t diffuse;
4837                 vec3_t diffusenormal;
4838                 vec_t brightness;
4839                 vec_t goal;
4840                 vec_t adjust;
4841                 vec_t current;
4842                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4843                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4844                 brightness = max(0.0000001f, brightness);
4845                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4846                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4847                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4848                 current = r_hdr_irisadaptation_value.value;
4849                 if (current < goal)
4850                         current = min(current + adjust, goal);
4851                 else if (current > goal)
4852                         current = max(current - adjust, goal);
4853                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4854                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4855         }
4856         else if (r_hdr_irisadaptation_value.value != 1.0f)
4857                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4858 }
4859
4860 static void R_View_SetFrustum(const int *scissor)
4861 {
4862         int i;
4863         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4864         vec3_t forward, left, up, origin, v;
4865
4866         if(scissor)
4867         {
4868                 // flipped x coordinates (because x points left here)
4869                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4870                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4871
4872                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4873                 switch(vid.renderpath)
4874                 {
4875                         case RENDERPATH_D3D9:
4876                         case RENDERPATH_D3D10:
4877                         case RENDERPATH_D3D11:
4878                         case RENDERPATH_SOFT:
4879                                 // non-flipped y coordinates
4880                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4881                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4882                                 break;
4883                         case RENDERPATH_GL11:
4884                         case RENDERPATH_GL13:
4885                         case RENDERPATH_GL20:
4886                         case RENDERPATH_GLES2:
4887                                 // non-flipped y coordinates
4888                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4889                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4890                                 break;
4891                 }
4892         }
4893
4894         // we can't trust r_refdef.view.forward and friends in reflected scenes
4895         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4896
4897 #if 0
4898         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4899         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4900         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4901         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4902         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4903         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4904         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4905         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4906         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4907         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4908         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4909         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4910 #endif
4911
4912 #if 0
4913         zNear = r_refdef.nearclip;
4914         nudge = 1.0 - 1.0 / (1<<23);
4915         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4916         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4917         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4918         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4919         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4920         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4921         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4922         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4923 #endif
4924
4925
4926
4927 #if 0
4928         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4929         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4930         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4931         r_refdef.view.frustum[0].dist = m[15] - m[12];
4932
4933         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4934         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4935         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4936         r_refdef.view.frustum[1].dist = m[15] + m[12];
4937
4938         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4939         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4940         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4941         r_refdef.view.frustum[2].dist = m[15] - m[13];
4942
4943         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4944         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4945         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4946         r_refdef.view.frustum[3].dist = m[15] + m[13];
4947
4948         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4949         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4950         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4951         r_refdef.view.frustum[4].dist = m[15] - m[14];
4952
4953         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4954         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4955         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4956         r_refdef.view.frustum[5].dist = m[15] + m[14];
4957 #endif
4958
4959         if (r_refdef.view.useperspective)
4960         {
4961                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4962                 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]);
4963                 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]);
4964                 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]);
4965                 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]);
4966
4967                 // then the normals from the corners relative to origin
4968                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4969                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4970                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4971                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4972
4973                 // in a NORMAL view, forward cross left == up
4974                 // in a REFLECTED view, forward cross left == down
4975                 // so our cross products above need to be adjusted for a left handed coordinate system
4976                 CrossProduct(forward, left, v);
4977                 if(DotProduct(v, up) < 0)
4978                 {
4979                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4980                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
4981                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
4982                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
4983                 }
4984
4985                 // Leaving those out was a mistake, those were in the old code, and they
4986                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4987                 // I couldn't reproduce it after adding those normalizations. --blub
4988                 VectorNormalize(r_refdef.view.frustum[0].normal);
4989                 VectorNormalize(r_refdef.view.frustum[1].normal);
4990                 VectorNormalize(r_refdef.view.frustum[2].normal);
4991                 VectorNormalize(r_refdef.view.frustum[3].normal);
4992
4993                 // make the corners absolute
4994                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
4995                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
4996                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
4997                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
4998
4999                 // one more normal
5000                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5001
5002                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5003                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5004                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5005                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5006                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5007         }
5008         else
5009         {
5010                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5011                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5012                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5013                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5014                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5015                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5016                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5017                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5018                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5019                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5020         }
5021         r_refdef.view.numfrustumplanes = 5;
5022
5023         if (r_refdef.view.useclipplane)
5024         {
5025                 r_refdef.view.numfrustumplanes = 6;
5026                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5027         }
5028
5029         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5030                 PlaneClassify(r_refdef.view.frustum + i);
5031
5032         // LordHavoc: note to all quake engine coders, Quake had a special case
5033         // for 90 degrees which assumed a square view (wrong), so I removed it,
5034         // Quake2 has it disabled as well.
5035
5036         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5037         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5038         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5039         //PlaneClassify(&frustum[0]);
5040
5041         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5042         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5043         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5044         //PlaneClassify(&frustum[1]);
5045
5046         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5047         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5048         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5049         //PlaneClassify(&frustum[2]);
5050
5051         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5052         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5053         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5054         //PlaneClassify(&frustum[3]);
5055
5056         // nearclip plane
5057         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5058         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5059         //PlaneClassify(&frustum[4]);
5060 }
5061
5062 void R_View_UpdateWithScissor(const int *myscissor)
5063 {
5064         R_Main_ResizeViewCache();
5065         R_View_SetFrustum(myscissor);
5066         R_View_WorldVisibility(r_refdef.view.useclipplane);
5067         R_View_UpdateEntityVisible();
5068         R_View_UpdateEntityLighting();
5069 }
5070
5071 void R_View_Update(void)
5072 {
5073         R_Main_ResizeViewCache();
5074         R_View_SetFrustum(NULL);
5075         R_View_WorldVisibility(r_refdef.view.useclipplane);
5076         R_View_UpdateEntityVisible();
5077         R_View_UpdateEntityLighting();
5078 }
5079
5080 void R_SetupView(qboolean allowwaterclippingplane)
5081 {
5082         const float *customclipplane = NULL;
5083         float plane[4];
5084         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5085         {
5086                 // LordHavoc: couldn't figure out how to make this approach the
5087                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5088                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5089                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5090                         dist = r_refdef.view.clipplane.dist;
5091                 plane[0] = r_refdef.view.clipplane.normal[0];
5092                 plane[1] = r_refdef.view.clipplane.normal[1];
5093                 plane[2] = r_refdef.view.clipplane.normal[2];
5094                 plane[3] = dist;
5095                 customclipplane = plane;
5096         }
5097
5098         if (!r_refdef.view.useperspective)
5099                 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);
5100         else if (vid.stencil && r_useinfinitefarclip.integer)
5101                 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);
5102         else
5103                 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);
5104         R_SetViewport(&r_refdef.view.viewport);
5105 }
5106
5107 void R_EntityMatrix(const matrix4x4_t *matrix)
5108 {
5109         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5110         {
5111                 gl_modelmatrixchanged = false;
5112                 gl_modelmatrix = *matrix;
5113                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5114                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5115                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5116                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5117                 CHECKGLERROR
5118                 switch(vid.renderpath)
5119                 {
5120                 case RENDERPATH_D3D9:
5121 #ifdef SUPPORTD3D
5122                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5123                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5124 #endif
5125                         break;
5126                 case RENDERPATH_D3D10:
5127                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5128                         break;
5129                 case RENDERPATH_D3D11:
5130                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5131                         break;
5132                 case RENDERPATH_GL13:
5133                 case RENDERPATH_GL11:
5134                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5135                         break;
5136                 case RENDERPATH_SOFT:
5137                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5138                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5139                         break;
5140                 case RENDERPATH_GL20:
5141                 case RENDERPATH_GLES2:
5142                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5143                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5144                         break;
5145                 }
5146         }
5147 }
5148
5149 void R_ResetViewRendering2D(void)
5150 {
5151         r_viewport_t viewport;
5152         DrawQ_Finish();
5153
5154         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5155         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);
5156         R_SetViewport(&viewport);
5157         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5158         GL_Color(1, 1, 1, 1);
5159         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5160         GL_BlendFunc(GL_ONE, GL_ZERO);
5161         GL_ScissorTest(false);
5162         GL_DepthMask(false);
5163         GL_DepthRange(0, 1);
5164         GL_DepthTest(false);
5165         GL_DepthFunc(GL_LEQUAL);
5166         R_EntityMatrix(&identitymatrix);
5167         R_Mesh_ResetTextureState();
5168         GL_PolygonOffset(0, 0);
5169         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5170         switch(vid.renderpath)
5171         {
5172         case RENDERPATH_GL11:
5173         case RENDERPATH_GL13:
5174         case RENDERPATH_GL20:
5175         case RENDERPATH_GLES2:
5176                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5177                 break;
5178         case RENDERPATH_D3D9:
5179         case RENDERPATH_D3D10:
5180         case RENDERPATH_D3D11:
5181         case RENDERPATH_SOFT:
5182                 break;
5183         }
5184         GL_CullFace(GL_NONE);
5185 }
5186
5187 void R_ResetViewRendering3D(void)
5188 {
5189         DrawQ_Finish();
5190
5191         R_SetupView(true);
5192         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5193         GL_Color(1, 1, 1, 1);
5194         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5195         GL_BlendFunc(GL_ONE, GL_ZERO);
5196         GL_ScissorTest(true);
5197         GL_DepthMask(true);
5198         GL_DepthRange(0, 1);
5199         GL_DepthTest(true);
5200         GL_DepthFunc(GL_LEQUAL);
5201         R_EntityMatrix(&identitymatrix);
5202         R_Mesh_ResetTextureState();
5203         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5204         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5205         switch(vid.renderpath)
5206         {
5207         case RENDERPATH_GL11:
5208         case RENDERPATH_GL13:
5209         case RENDERPATH_GL20:
5210         case RENDERPATH_GLES2:
5211                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5212                 break;
5213         case RENDERPATH_D3D9:
5214         case RENDERPATH_D3D10:
5215         case RENDERPATH_D3D11:
5216         case RENDERPATH_SOFT:
5217                 break;
5218         }
5219         GL_CullFace(r_refdef.view.cullface_back);
5220 }
5221
5222 /*
5223 ================
5224 R_RenderView_UpdateViewVectors
5225 ================
5226 */
5227 static void R_RenderView_UpdateViewVectors(void)
5228 {
5229         // break apart the view matrix into vectors for various purposes
5230         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5231         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5232         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5233         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5234         // make an inverted copy of the view matrix for tracking sprites
5235         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5236 }
5237
5238 void R_RenderScene(void);
5239 void R_RenderWaterPlanes(void);
5240
5241 static void R_Water_StartFrame(void)
5242 {
5243         int i;
5244         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5245         r_waterstate_waterplane_t *p;
5246
5247         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5248                 return;
5249
5250         switch(vid.renderpath)
5251         {
5252         case RENDERPATH_GL20:
5253         case RENDERPATH_D3D9:
5254         case RENDERPATH_D3D10:
5255         case RENDERPATH_D3D11:
5256         case RENDERPATH_SOFT:
5257         case RENDERPATH_GLES2:
5258                 break;
5259         case RENDERPATH_GL13:
5260         case RENDERPATH_GL11:
5261                 return;
5262         }
5263
5264         // set waterwidth and waterheight to the water resolution that will be
5265         // used (often less than the screen resolution for faster rendering)
5266         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5267         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5268
5269         // calculate desired texture sizes
5270         // can't use water if the card does not support the texture size
5271         if (!r_water.integer || r_showsurfaces.integer)
5272                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5273         else if (vid.support.arb_texture_non_power_of_two)
5274         {
5275                 texturewidth = waterwidth;
5276                 textureheight = waterheight;
5277                 camerawidth = waterwidth;
5278                 cameraheight = waterheight;
5279         }
5280         else
5281         {
5282                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5283                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5284                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5285                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5286         }
5287
5288         // allocate textures as needed
5289         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5290         {
5291                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5292                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5293                 {
5294                         if (p->texture_refraction)
5295                                 R_FreeTexture(p->texture_refraction);
5296                         p->texture_refraction = NULL;
5297                         if (p->texture_reflection)
5298                                 R_FreeTexture(p->texture_reflection);
5299                         p->texture_reflection = NULL;
5300                         if (p->texture_camera)
5301                                 R_FreeTexture(p->texture_camera);
5302                         p->texture_camera = NULL;
5303                 }
5304                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5305                 r_waterstate.texturewidth = texturewidth;
5306                 r_waterstate.textureheight = textureheight;
5307                 r_waterstate.camerawidth = camerawidth;
5308                 r_waterstate.cameraheight = cameraheight;
5309         }
5310
5311         if (r_waterstate.texturewidth)
5312         {
5313                 r_waterstate.enabled = true;
5314
5315                 // when doing a reduced render (HDR) we want to use a smaller area
5316                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5317                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5318
5319                 // set up variables that will be used in shader setup
5320                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5321                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5322                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5323                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5324         }
5325
5326         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5327         r_waterstate.numwaterplanes = 0;
5328 }
5329
5330 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5331 {
5332         int triangleindex, planeindex;
5333         const int *e;
5334         vec3_t vert[3];
5335         vec3_t normal;
5336         vec3_t center;
5337         mplane_t plane;
5338         r_waterstate_waterplane_t *p;
5339         texture_t *t = R_GetCurrentTexture(surface->texture);
5340
5341         // just use the first triangle with a valid normal for any decisions
5342         VectorClear(normal);
5343         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5344         {
5345                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5346                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5347                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5348                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5349                 if (VectorLength2(normal) >= 0.001)
5350                         break;
5351         }
5352
5353         VectorCopy(normal, plane.normal);
5354         VectorNormalize(plane.normal);
5355         plane.dist = DotProduct(vert[0], plane.normal);
5356         PlaneClassify(&plane);
5357         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5358         {
5359                 // skip backfaces (except if nocullface is set)
5360                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5361                         return;
5362                 VectorNegate(plane.normal, plane.normal);
5363                 plane.dist *= -1;
5364                 PlaneClassify(&plane);
5365         }
5366
5367
5368         // find a matching plane if there is one
5369         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5370                 if(p->camera_entity == t->camera_entity)
5371                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5372                                 break;
5373         if (planeindex >= r_waterstate.maxwaterplanes)
5374                 return; // nothing we can do, out of planes
5375
5376         // if this triangle does not fit any known plane rendered this frame, add one
5377         if (planeindex >= r_waterstate.numwaterplanes)
5378         {
5379                 // store the new plane
5380                 r_waterstate.numwaterplanes++;
5381                 p->plane = plane;
5382                 // clear materialflags and pvs
5383                 p->materialflags = 0;
5384                 p->pvsvalid = false;
5385                 p->camera_entity = t->camera_entity;
5386                 VectorCopy(surface->mins, p->mins);
5387                 VectorCopy(surface->maxs, p->maxs);
5388         }
5389         else
5390         {
5391                 // merge mins/maxs
5392                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5393                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5394                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5395                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5396                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5397                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5398         }
5399         // merge this surface's materialflags into the waterplane
5400         p->materialflags |= t->currentmaterialflags;
5401         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5402         {
5403                 // merge this surface's PVS into the waterplane
5404                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5405                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5406                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5407                 {
5408                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5409                         p->pvsvalid = true;
5410                 }
5411         }
5412 }
5413
5414 static void R_Water_ProcessPlanes(void)
5415 {
5416         int myscissor[4];
5417         r_refdef_view_t originalview;
5418         r_refdef_view_t myview;
5419         int planeindex;
5420         r_waterstate_waterplane_t *p;
5421         vec3_t visorigin;
5422
5423         originalview = r_refdef.view;
5424
5425         // make sure enough textures are allocated
5426         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5427         {
5428                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5429                 {
5430                         if (!p->texture_refraction)
5431                                 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);
5432                         if (!p->texture_refraction)
5433                                 goto error;
5434                 }
5435                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5436                 {
5437                         if (!p->texture_camera)
5438                                 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);
5439                         if (!p->texture_camera)
5440                                 goto error;
5441                 }
5442
5443                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5444                 {
5445                         if (!p->texture_reflection)
5446                                 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);
5447                         if (!p->texture_reflection)
5448                                 goto error;
5449                 }
5450         }
5451
5452         // render views
5453         r_refdef.view = originalview;
5454         r_refdef.view.showdebug = false;
5455         r_refdef.view.width = r_waterstate.waterwidth;
5456         r_refdef.view.height = r_waterstate.waterheight;
5457         r_refdef.view.useclipplane = true;
5458         myview = r_refdef.view;
5459         r_waterstate.renderingscene = true;
5460         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5461         {
5462                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5463                 {
5464                         r_refdef.view = myview;
5465                         if(r_water_scissormode.integer)
5466                         {
5467                                 R_SetupView(true);
5468                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5469                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5470                         }
5471
5472                         // render reflected scene and copy into texture
5473                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5474                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5475                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5476                         r_refdef.view.clipplane = p->plane;
5477
5478                         // reverse the cullface settings for this render
5479                         r_refdef.view.cullface_front = GL_FRONT;
5480                         r_refdef.view.cullface_back = GL_BACK;
5481                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5482                         {
5483                                 r_refdef.view.usecustompvs = true;
5484                                 if (p->pvsvalid)
5485                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5486                                 else
5487                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5488                         }
5489
5490                         R_ResetViewRendering3D();
5491                         R_ClearScreen(r_refdef.fogenabled);
5492                         if(r_water_scissormode.integer & 2)
5493                                 R_View_UpdateWithScissor(myscissor);
5494                         else
5495                                 R_View_Update();
5496                         if(r_water_scissormode.integer & 1)
5497                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5498                         R_RenderScene();
5499
5500                         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);
5501                 }
5502
5503                 // render the normal view scene and copy into texture
5504                 // (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)
5505                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5506                 {
5507                         r_refdef.view = myview;
5508                         if(r_water_scissormode.integer)
5509                         {
5510                                 R_SetupView(true);
5511                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5512                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5513                         }
5514
5515                         r_waterstate.renderingrefraction = true;
5516
5517                         r_refdef.view.clipplane = p->plane;
5518                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5519                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5520
5521                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5522                         {
5523                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5524                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5525                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5526                                 R_RenderView_UpdateViewVectors();
5527                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5528                                 {
5529                                         r_refdef.view.usecustompvs = true;
5530                                         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);
5531                                 }
5532                         }
5533
5534                         PlaneClassify(&r_refdef.view.clipplane);
5535
5536                         R_ResetViewRendering3D();
5537                         R_ClearScreen(r_refdef.fogenabled);
5538                         if(r_water_scissormode.integer & 2)
5539                                 R_View_UpdateWithScissor(myscissor);
5540                         else
5541                                 R_View_Update();
5542                         if(r_water_scissormode.integer & 1)
5543                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5544                         R_RenderScene();
5545
5546                         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);
5547                         r_waterstate.renderingrefraction = false;
5548                 }
5549                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5550                 {
5551                         r_refdef.view = myview;
5552
5553                         r_refdef.view.clipplane = p->plane;
5554                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5555                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5556
5557                         r_refdef.view.width = r_waterstate.camerawidth;
5558                         r_refdef.view.height = r_waterstate.cameraheight;
5559                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5560                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5561
5562                         if(p->camera_entity)
5563                         {
5564                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5565                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5566                         }
5567
5568                         // note: all of the view is used for displaying... so
5569                         // there is no use in scissoring
5570
5571                         // reverse the cullface settings for this render
5572                         r_refdef.view.cullface_front = GL_FRONT;
5573                         r_refdef.view.cullface_back = GL_BACK;
5574                         // also reverse the view matrix
5575                         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
5576                         R_RenderView_UpdateViewVectors();
5577                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5578                         {
5579                                 r_refdef.view.usecustompvs = true;
5580                                 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);
5581                         }
5582                         
5583                         // camera needs no clipplane
5584                         r_refdef.view.useclipplane = false;
5585
5586                         PlaneClassify(&r_refdef.view.clipplane);
5587
5588                         R_ResetViewRendering3D();
5589                         R_ClearScreen(r_refdef.fogenabled);
5590                         R_View_Update();
5591                         R_RenderScene();
5592
5593                         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);
5594                         r_waterstate.renderingrefraction = false;
5595                 }
5596
5597         }
5598         r_waterstate.renderingscene = false;
5599         r_refdef.view = originalview;
5600         R_ResetViewRendering3D();
5601         R_ClearScreen(r_refdef.fogenabled);
5602         R_View_Update();
5603         return;
5604 error:
5605         r_refdef.view = originalview;
5606         r_waterstate.renderingscene = false;
5607         Cvar_SetValueQuick(&r_water, 0);
5608         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5609         return;
5610 }
5611
5612 void R_Bloom_StartFrame(void)
5613 {
5614         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5615
5616         switch(vid.renderpath)
5617         {
5618         case RENDERPATH_GL20:
5619         case RENDERPATH_D3D9:
5620         case RENDERPATH_D3D10:
5621         case RENDERPATH_D3D11:
5622         case RENDERPATH_SOFT:
5623         case RENDERPATH_GLES2:
5624                 break;
5625         case RENDERPATH_GL13:
5626         case RENDERPATH_GL11:
5627                 return;
5628         }
5629
5630         // set bloomwidth and bloomheight to the bloom resolution that will be
5631         // used (often less than the screen resolution for faster rendering)
5632         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5633         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5634         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5635         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5636         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5637
5638         // calculate desired texture sizes
5639         if (vid.support.arb_texture_non_power_of_two)
5640         {
5641                 screentexturewidth = r_refdef.view.width;
5642                 screentextureheight = r_refdef.view.height;
5643                 bloomtexturewidth = r_bloomstate.bloomwidth;
5644                 bloomtextureheight = r_bloomstate.bloomheight;
5645         }
5646         else
5647         {
5648                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5649                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5650                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5651                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5652         }
5653
5654         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))
5655         {
5656                 Cvar_SetValueQuick(&r_hdr, 0);
5657                 Cvar_SetValueQuick(&r_bloom, 0);
5658                 Cvar_SetValueQuick(&r_motionblur, 0);
5659                 Cvar_SetValueQuick(&r_damageblur, 0);
5660         }
5661
5662         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)))
5663                 screentexturewidth = screentextureheight = 0;
5664         if (!r_hdr.integer && !r_bloom.integer)
5665                 bloomtexturewidth = bloomtextureheight = 0;
5666
5667         // allocate textures as needed
5668         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5669         {
5670                 if (r_bloomstate.texture_screen)
5671                         R_FreeTexture(r_bloomstate.texture_screen);
5672                 r_bloomstate.texture_screen = NULL;
5673                 r_bloomstate.screentexturewidth = screentexturewidth;
5674                 r_bloomstate.screentextureheight = screentextureheight;
5675                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5676                         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);
5677         }
5678         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5679         {
5680                 if (r_bloomstate.texture_bloom)
5681                         R_FreeTexture(r_bloomstate.texture_bloom);
5682                 r_bloomstate.texture_bloom = NULL;
5683                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5684                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5685                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5686                         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);
5687         }
5688
5689         // when doing a reduced render (HDR) we want to use a smaller area
5690         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5691         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5692         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5693         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5694         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5695
5696         // set up a texcoord array for the full resolution screen image
5697         // (we have to keep this around to copy back during final render)
5698         r_bloomstate.screentexcoord2f[0] = 0;
5699         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5700         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5701         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5702         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5703         r_bloomstate.screentexcoord2f[5] = 0;
5704         r_bloomstate.screentexcoord2f[6] = 0;
5705         r_bloomstate.screentexcoord2f[7] = 0;
5706
5707         // set up a texcoord array for the reduced resolution bloom image
5708         // (which will be additive blended over the screen image)
5709         r_bloomstate.bloomtexcoord2f[0] = 0;
5710         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5711         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5712         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5713         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5714         r_bloomstate.bloomtexcoord2f[5] = 0;
5715         r_bloomstate.bloomtexcoord2f[6] = 0;
5716         r_bloomstate.bloomtexcoord2f[7] = 0;
5717
5718         switch(vid.renderpath)
5719         {
5720         case RENDERPATH_GL11:
5721         case RENDERPATH_GL13:
5722         case RENDERPATH_GL20:
5723         case RENDERPATH_SOFT:
5724         case RENDERPATH_GLES2:
5725                 break;
5726         case RENDERPATH_D3D9:
5727         case RENDERPATH_D3D10:
5728         case RENDERPATH_D3D11:
5729                 {
5730                         int i;
5731                         for (i = 0;i < 4;i++)
5732                         {
5733                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5734                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5735                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5736                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5737                         }
5738                 }
5739                 break;
5740         }
5741
5742         if (r_hdr.integer || r_bloom.integer)
5743         {
5744                 r_bloomstate.enabled = true;
5745                 r_bloomstate.hdr = r_hdr.integer != 0;
5746         }
5747
5748         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);
5749 }
5750
5751 void R_Bloom_CopyBloomTexture(float colorscale)
5752 {
5753         r_refdef.stats.bloom++;
5754
5755         // scale down screen texture to the bloom texture size
5756         CHECKGLERROR
5757         R_SetViewport(&r_bloomstate.viewport);
5758         GL_BlendFunc(GL_ONE, GL_ZERO);
5759         GL_Color(colorscale, colorscale, colorscale, 1);
5760         // 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...
5761         switch(vid.renderpath)
5762         {
5763         case RENDERPATH_GL11:
5764         case RENDERPATH_GL13:
5765         case RENDERPATH_GL20:
5766         case RENDERPATH_SOFT:
5767         case RENDERPATH_GLES2:
5768                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5769                 break;
5770         case RENDERPATH_D3D9:
5771         case RENDERPATH_D3D10:
5772         case RENDERPATH_D3D11:
5773                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5774                 break;
5775         }
5776         // TODO: do boxfilter scale-down in shader?
5777         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5778         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5779         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5780
5781         // we now have a bloom image in the framebuffer
5782         // copy it into the bloom image texture for later processing
5783         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);
5784         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5785 }
5786
5787 void R_Bloom_CopyHDRTexture(void)
5788 {
5789         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);
5790         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5791 }
5792
5793 void R_Bloom_MakeTexture(void)
5794 {
5795         int x, range, dir;
5796         float xoffset, yoffset, r, brighten;
5797
5798         r_refdef.stats.bloom++;
5799
5800         R_ResetViewRendering2D();
5801
5802         // we have a bloom image in the framebuffer
5803         CHECKGLERROR
5804         R_SetViewport(&r_bloomstate.viewport);
5805
5806         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5807         {
5808                 x *= 2;
5809                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5810                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5811                 GL_Color(r,r,r,1);
5812                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5813                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5814                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5815                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5816
5817                 // copy the vertically blurred bloom view to a texture
5818                 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);
5819                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5820         }
5821
5822         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5823         brighten = r_bloom_brighten.value;
5824         if (r_hdr.integer)
5825                 brighten *= r_hdr_range.value;
5826         brighten = sqrt(brighten);
5827         if(range >= 1)
5828                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5829         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5830
5831         for (dir = 0;dir < 2;dir++)
5832         {
5833                 // blend on at multiple vertical offsets to achieve a vertical blur
5834                 // TODO: do offset blends using GLSL
5835                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5836                 GL_BlendFunc(GL_ONE, GL_ZERO);
5837                 for (x = -range;x <= range;x++)
5838                 {
5839                         if (!dir){xoffset = 0;yoffset = x;}
5840                         else {xoffset = x;yoffset = 0;}
5841                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5842                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5843                         // compute a texcoord array with the specified x and y offset
5844                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5845                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5846                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5847                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5848                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5849                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5850                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5851                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5852                         // this r value looks like a 'dot' particle, fading sharply to
5853                         // black at the edges
5854                         // (probably not realistic but looks good enough)
5855                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5856                         //r = brighten/(range*2+1);
5857                         r = brighten / (range * 2 + 1);
5858                         if(range >= 1)
5859                                 r *= (1 - x*x/(float)(range*range));
5860                         GL_Color(r, r, r, 1);
5861                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5862                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5863                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5864                         GL_BlendFunc(GL_ONE, GL_ONE);
5865                 }
5866
5867                 // copy the vertically blurred bloom view to a texture
5868                 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);
5869                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5870         }
5871 }
5872
5873 void R_HDR_RenderBloomTexture(void)
5874 {
5875         int oldwidth, oldheight;
5876         float oldcolorscale;
5877         qboolean oldwaterstate;
5878
5879         oldwaterstate = r_waterstate.enabled;
5880         oldcolorscale = r_refdef.view.colorscale;
5881         oldwidth = r_refdef.view.width;
5882         oldheight = r_refdef.view.height;
5883         r_refdef.view.width = r_bloomstate.bloomwidth;
5884         r_refdef.view.height = r_bloomstate.bloomheight;
5885
5886         if(r_hdr.integer < 2)
5887                 r_waterstate.enabled = false;
5888
5889         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5890         // TODO: add exposure compensation features
5891         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5892
5893         r_refdef.view.showdebug = false;
5894         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5895
5896         R_ResetViewRendering3D();
5897
5898         R_ClearScreen(r_refdef.fogenabled);
5899         if (r_timereport_active)
5900                 R_TimeReport("HDRclear");
5901
5902         R_View_Update();
5903         if (r_timereport_active)
5904                 R_TimeReport("visibility");
5905
5906         // only do secondary renders with HDR if r_hdr is 2 or higher
5907         r_waterstate.numwaterplanes = 0;
5908         if (r_waterstate.enabled)
5909                 R_RenderWaterPlanes();
5910
5911         r_refdef.view.showdebug = true;
5912         R_RenderScene();
5913         r_waterstate.numwaterplanes = 0;
5914
5915         R_ResetViewRendering2D();
5916
5917         R_Bloom_CopyHDRTexture();
5918         R_Bloom_MakeTexture();
5919
5920         // restore the view settings
5921         r_waterstate.enabled = oldwaterstate;
5922         r_refdef.view.width = oldwidth;
5923         r_refdef.view.height = oldheight;
5924         r_refdef.view.colorscale = oldcolorscale;
5925
5926         R_ResetViewRendering3D();
5927
5928         R_ClearScreen(r_refdef.fogenabled);
5929         if (r_timereport_active)
5930                 R_TimeReport("viewclear");
5931 }
5932
5933 static void R_BlendView(void)
5934 {
5935         unsigned int permutation;
5936         float uservecs[4][4];
5937
5938         switch (vid.renderpath)
5939         {
5940         case RENDERPATH_GL20:
5941         case RENDERPATH_D3D9:
5942         case RENDERPATH_D3D10:
5943         case RENDERPATH_D3D11:
5944         case RENDERPATH_SOFT:
5945         case RENDERPATH_GLES2:
5946                 permutation =
5947                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5948                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5949                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5950                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5951                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5952
5953                 if (r_bloomstate.texture_screen)
5954                 {
5955                         // make sure the buffer is available
5956                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5957
5958                         R_ResetViewRendering2D();
5959
5960                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5961                         {
5962                                 // declare variables
5963                                 float speed;
5964                                 static float avgspeed;
5965
5966                                 speed = VectorLength(cl.movement_velocity);
5967
5968                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5969                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5970
5971                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5972                                 speed = bound(0, speed, 1);
5973                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5974
5975                                 // calculate values into a standard alpha
5976                                 cl.motionbluralpha = 1 - exp(-
5977                                                 (
5978                                                  (r_motionblur.value * speed / 80)
5979                                                  +
5980                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5981                                                 )
5982                                                 /
5983                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
5984                                            );
5985
5986                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5987                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5988                                 // apply the blur
5989                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
5990                                 {
5991                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5992                                         GL_Color(1, 1, 1, cl.motionbluralpha);
5993                                         switch(vid.renderpath)
5994                                         {
5995                                         case RENDERPATH_GL11:
5996                                         case RENDERPATH_GL13:
5997                                         case RENDERPATH_GL20:
5998                                         case RENDERPATH_SOFT:
5999                                         case RENDERPATH_GLES2:
6000                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6001                                                 break;
6002                                         case RENDERPATH_D3D9:
6003                                         case RENDERPATH_D3D10:
6004                                         case RENDERPATH_D3D11:
6005                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6006                                                 break;
6007                                         }
6008                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6009                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6010                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6011                                 }
6012                         }
6013
6014                         // copy view into the screen texture
6015                         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);
6016                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6017                 }
6018                 else if (!r_bloomstate.texture_bloom)
6019                 {
6020                         // we may still have to do view tint...
6021                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6022                         {
6023                                 // apply a color tint to the whole view
6024                                 R_ResetViewRendering2D();
6025                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6026                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6027                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6028                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6029                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6030                         }
6031                         break; // no screen processing, no bloom, skip it
6032                 }
6033
6034                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6035                 {
6036                         // render simple bloom effect
6037                         // copy the screen and shrink it and darken it for the bloom process
6038                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6039                         // make the bloom texture
6040                         R_Bloom_MakeTexture();
6041                 }
6042
6043 #if _MSC_VER >= 1400
6044 #define sscanf sscanf_s
6045 #endif
6046                 memset(uservecs, 0, sizeof(uservecs));
6047                 if (r_glsl_postprocess_uservec1_enable.integer)
6048                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6049                 if (r_glsl_postprocess_uservec2_enable.integer)
6050                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6051                 if (r_glsl_postprocess_uservec3_enable.integer)
6052                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6053                 if (r_glsl_postprocess_uservec4_enable.integer)
6054                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6055
6056                 R_ResetViewRendering2D();
6057                 GL_Color(1, 1, 1, 1);
6058                 GL_BlendFunc(GL_ONE, GL_ZERO);
6059
6060                 switch(vid.renderpath)
6061                 {
6062                 case RENDERPATH_GL20:
6063                 case RENDERPATH_GLES2:
6064                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6065                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6066                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6067                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6068                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6069                         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]);
6070                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6071                         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]);
6072                         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]);
6073                         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]);
6074                         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]);
6075                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6076                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6077                         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);
6078                         break;
6079                 case RENDERPATH_D3D9:
6080 #ifdef SUPPORTD3D
6081                         // 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...
6082                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6083                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6084                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6085                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6086                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6087                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6088                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6089                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6090                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6091                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6092                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6093                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6094                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6095                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6096 #endif
6097                         break;
6098                 case RENDERPATH_D3D10:
6099                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6100                         break;
6101                 case RENDERPATH_D3D11:
6102                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6103                         break;
6104                 case RENDERPATH_SOFT:
6105                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6106                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6107                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6108                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6109                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6110                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6111                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6112                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6113                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6114                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6115                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6116                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6117                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6118                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6119                         break;
6120                 default:
6121                         break;
6122                 }
6123                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6124                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6125                 break;
6126         case RENDERPATH_GL13:
6127         case RENDERPATH_GL11:
6128                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6129                 {
6130                         // apply a color tint to the whole view
6131                         R_ResetViewRendering2D();
6132                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6133                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6134                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6135                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6136                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6137                 }
6138                 break;
6139         }
6140 }
6141
6142 matrix4x4_t r_waterscrollmatrix;
6143
6144 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6145 {
6146         if (r_refdef.fog_density)
6147         {
6148                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6149                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6150                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6151
6152                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6153                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6154                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6155                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6156
6157                 {
6158                         vec3_t fogvec;
6159                         VectorCopy(r_refdef.fogcolor, fogvec);
6160                         //   color.rgb *= ContrastBoost * SceneBrightness;
6161                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6162                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6163                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6164                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6165                 }
6166         }
6167 }
6168
6169 void R_UpdateVariables(void)
6170 {
6171         R_Textures_Frame();
6172
6173         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6174
6175         r_refdef.farclip = r_farclip_base.value;
6176         if (r_refdef.scene.worldmodel)
6177                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6178         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6179
6180         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6181                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6182         r_refdef.polygonfactor = 0;
6183         r_refdef.polygonoffset = 0;
6184         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6185         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6186
6187         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6188         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6189         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6190         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6191         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6192         if (FAKELIGHT_ENABLED)
6193         {
6194                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6195         }
6196         if (r_showsurfaces.integer)
6197         {
6198                 r_refdef.scene.rtworld = false;
6199                 r_refdef.scene.rtworldshadows = false;
6200                 r_refdef.scene.rtdlight = false;
6201                 r_refdef.scene.rtdlightshadows = false;
6202                 r_refdef.lightmapintensity = 0;
6203         }
6204
6205         if (gamemode == GAME_NEHAHRA)
6206         {
6207                 if (gl_fogenable.integer)
6208                 {
6209                         r_refdef.oldgl_fogenable = true;
6210                         r_refdef.fog_density = gl_fogdensity.value;
6211                         r_refdef.fog_red = gl_fogred.value;
6212                         r_refdef.fog_green = gl_foggreen.value;
6213                         r_refdef.fog_blue = gl_fogblue.value;
6214                         r_refdef.fog_alpha = 1;
6215                         r_refdef.fog_start = 0;
6216                         r_refdef.fog_end = gl_skyclip.value;
6217                         r_refdef.fog_height = 1<<30;
6218                         r_refdef.fog_fadedepth = 128;
6219                 }
6220                 else if (r_refdef.oldgl_fogenable)
6221                 {
6222                         r_refdef.oldgl_fogenable = false;
6223                         r_refdef.fog_density = 0;
6224                         r_refdef.fog_red = 0;
6225                         r_refdef.fog_green = 0;
6226                         r_refdef.fog_blue = 0;
6227                         r_refdef.fog_alpha = 0;
6228                         r_refdef.fog_start = 0;
6229                         r_refdef.fog_end = 0;
6230                         r_refdef.fog_height = 1<<30;
6231                         r_refdef.fog_fadedepth = 128;
6232                 }
6233         }
6234
6235         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6236         r_refdef.fog_start = max(0, r_refdef.fog_start);
6237         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6238
6239         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6240
6241         if (r_refdef.fog_density && r_drawfog.integer)
6242         {
6243                 r_refdef.fogenabled = true;
6244                 // this is the point where the fog reaches 0.9986 alpha, which we
6245                 // consider a good enough cutoff point for the texture
6246                 // (0.9986 * 256 == 255.6)
6247                 if (r_fog_exp2.integer)
6248                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6249                 else
6250                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6251                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6252                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6253                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6254                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6255                         R_BuildFogHeightTexture();
6256                 // fog color was already set
6257                 // update the fog texture
6258                 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)
6259                         R_BuildFogTexture();
6260                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6261                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6262         }
6263         else
6264                 r_refdef.fogenabled = false;
6265
6266         switch(vid.renderpath)
6267         {
6268         case RENDERPATH_GL20:
6269         case RENDERPATH_D3D9:
6270         case RENDERPATH_D3D10:
6271         case RENDERPATH_D3D11:
6272         case RENDERPATH_SOFT:
6273         case RENDERPATH_GLES2:
6274                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6275                 {
6276                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6277                         {
6278                                 // build GLSL gamma texture
6279 #define RAMPWIDTH 256
6280                                 unsigned short ramp[RAMPWIDTH * 3];
6281                                 unsigned char rampbgr[RAMPWIDTH][4];
6282                                 int i;
6283
6284                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6285
6286                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6287                                 for(i = 0; i < RAMPWIDTH; ++i)
6288                                 {
6289                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6290                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6291                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6292                                         rampbgr[i][3] = 0;
6293                                 }
6294                                 if (r_texture_gammaramps)
6295                                 {
6296                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6297                                 }
6298                                 else
6299                                 {
6300                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6301                                 }
6302                         }
6303                 }
6304                 else
6305                 {
6306                         // remove GLSL gamma texture
6307                 }
6308                 break;
6309         case RENDERPATH_GL13:
6310         case RENDERPATH_GL11:
6311                 break;
6312         }
6313 }
6314
6315 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6316 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6317 /*
6318 ================
6319 R_SelectScene
6320 ================
6321 */
6322 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6323         if( scenetype != r_currentscenetype ) {
6324                 // store the old scenetype
6325                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6326                 r_currentscenetype = scenetype;
6327                 // move in the new scene
6328                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6329         }
6330 }
6331
6332 /*
6333 ================
6334 R_GetScenePointer
6335 ================
6336 */
6337 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6338 {
6339         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6340         if( scenetype == r_currentscenetype ) {
6341                 return &r_refdef.scene;
6342         } else {
6343                 return &r_scenes_store[ scenetype ];
6344         }
6345 }
6346
6347 /*
6348 ================
6349 R_RenderView
6350 ================
6351 */
6352 int dpsoftrast_test;
6353 void R_RenderView(void)
6354 {
6355         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6356
6357         dpsoftrast_test = r_test.integer;
6358
6359         if (r_timereport_active)
6360                 R_TimeReport("start");
6361         r_textureframe++; // used only by R_GetCurrentTexture
6362         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6363
6364         if(R_CompileShader_CheckStaticParms())
6365                 R_GLSL_Restart_f();
6366
6367         if (!r_drawentities.integer)
6368                 r_refdef.scene.numentities = 0;
6369
6370         R_AnimCache_ClearCache();
6371         R_FrameData_NewFrame();
6372
6373         /* adjust for stereo display */
6374         if(R_Stereo_Active())
6375         {
6376                 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);
6377                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6378         }
6379
6380         if (r_refdef.view.isoverlay)
6381         {
6382                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6383                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6384                 R_TimeReport("depthclear");
6385
6386                 r_refdef.view.showdebug = false;
6387
6388                 r_waterstate.enabled = false;
6389                 r_waterstate.numwaterplanes = 0;
6390
6391                 R_RenderScene();
6392
6393                 r_refdef.view.matrix = originalmatrix;
6394
6395                 CHECKGLERROR
6396                 return;
6397         }
6398
6399         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6400         {
6401                 r_refdef.view.matrix = originalmatrix;
6402                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6403         }
6404
6405         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6406
6407         R_RenderView_UpdateViewVectors();
6408
6409         R_Shadow_UpdateWorldLightSelection();
6410
6411         R_Bloom_StartFrame();
6412         R_Water_StartFrame();
6413
6414         CHECKGLERROR
6415         if (r_timereport_active)
6416                 R_TimeReport("viewsetup");
6417
6418         R_ResetViewRendering3D();
6419
6420         if (r_refdef.view.clear || r_refdef.fogenabled)
6421         {
6422                 R_ClearScreen(r_refdef.fogenabled);
6423                 if (r_timereport_active)
6424                         R_TimeReport("viewclear");
6425         }
6426         r_refdef.view.clear = true;
6427
6428         // this produces a bloom texture to be used in R_BlendView() later
6429         if (r_hdr.integer && r_bloomstate.bloomwidth)
6430         {
6431                 R_HDR_RenderBloomTexture();
6432                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6433                 r_textureframe++; // used only by R_GetCurrentTexture
6434         }
6435
6436         r_refdef.view.showdebug = true;
6437
6438         R_View_Update();
6439         if (r_timereport_active)
6440                 R_TimeReport("visibility");
6441
6442         r_waterstate.numwaterplanes = 0;
6443         if (r_waterstate.enabled)
6444                 R_RenderWaterPlanes();
6445
6446         R_RenderScene();
6447         r_waterstate.numwaterplanes = 0;
6448
6449         R_BlendView();
6450         if (r_timereport_active)
6451                 R_TimeReport("blendview");
6452
6453         GL_Scissor(0, 0, vid.width, vid.height);
6454         GL_ScissorTest(false);
6455
6456         r_refdef.view.matrix = originalmatrix;
6457
6458         CHECKGLERROR
6459 }
6460
6461 void R_RenderWaterPlanes(void)
6462 {
6463         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6464         {
6465                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6466                 if (r_timereport_active)
6467                         R_TimeReport("waterworld");
6468         }
6469
6470         // don't let sound skip if going slow
6471         if (r_refdef.scene.extraupdate)
6472                 S_ExtraUpdate ();
6473
6474         R_DrawModelsAddWaterPlanes();
6475         if (r_timereport_active)
6476                 R_TimeReport("watermodels");
6477
6478         if (r_waterstate.numwaterplanes)
6479         {
6480                 R_Water_ProcessPlanes();
6481                 if (r_timereport_active)
6482                         R_TimeReport("waterscenes");
6483         }
6484 }
6485
6486 extern void R_DrawLightningBeams (void);
6487 extern void VM_CL_AddPolygonsToMeshQueue (void);
6488 extern void R_DrawPortals (void);
6489 extern cvar_t cl_locs_show;
6490 static void R_DrawLocs(void);
6491 static void R_DrawEntityBBoxes(void);
6492 static void R_DrawModelDecals(void);
6493 extern void R_DrawModelShadows(void);
6494 extern void R_DrawModelShadowMaps(void);
6495 extern cvar_t cl_decals_newsystem;
6496 extern qboolean r_shadow_usingdeferredprepass;
6497 void R_RenderScene(void)
6498 {
6499         qboolean shadowmapping = false;
6500
6501         if (r_timereport_active)
6502                 R_TimeReport("beginscene");
6503
6504         r_refdef.stats.renders++;
6505
6506         R_UpdateFogColor();
6507
6508         // don't let sound skip if going slow
6509         if (r_refdef.scene.extraupdate)
6510                 S_ExtraUpdate ();
6511
6512         R_MeshQueue_BeginScene();
6513
6514         R_SkyStartFrame();
6515
6516         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);
6517
6518         if (r_timereport_active)
6519                 R_TimeReport("skystartframe");
6520
6521         if (cl.csqc_vidvars.drawworld)
6522         {
6523                 // don't let sound skip if going slow
6524                 if (r_refdef.scene.extraupdate)
6525                         S_ExtraUpdate ();
6526
6527                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6528                 {
6529                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6530                         if (r_timereport_active)
6531                                 R_TimeReport("worldsky");
6532                 }
6533
6534                 if (R_DrawBrushModelsSky() && r_timereport_active)
6535                         R_TimeReport("bmodelsky");
6536
6537                 if (skyrendermasked && skyrenderlater)
6538                 {
6539                         // we have to force off the water clipping plane while rendering sky
6540                         R_SetupView(false);
6541                         R_Sky();
6542                         R_SetupView(true);
6543                         if (r_timereport_active)
6544                                 R_TimeReport("sky");
6545                 }
6546         }
6547
6548         R_AnimCache_CacheVisibleEntities();
6549         if (r_timereport_active)
6550                 R_TimeReport("animation");
6551
6552         R_Shadow_PrepareLights();
6553         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6554                 R_Shadow_PrepareModelShadows();
6555         if (r_timereport_active)
6556                 R_TimeReport("preparelights");
6557
6558         if (R_Shadow_ShadowMappingEnabled())
6559                 shadowmapping = true;
6560
6561         if (r_shadow_usingdeferredprepass)
6562                 R_Shadow_DrawPrepass();
6563
6564         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6565         {
6566                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6567                 if (r_timereport_active)
6568                         R_TimeReport("worlddepth");
6569         }
6570         if (r_depthfirst.integer >= 2)
6571         {
6572                 R_DrawModelsDepth();
6573                 if (r_timereport_active)
6574                         R_TimeReport("modeldepth");
6575         }
6576
6577         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6578         {
6579                 R_DrawModelShadowMaps();
6580                 R_ResetViewRendering3D();
6581                 // don't let sound skip if going slow
6582                 if (r_refdef.scene.extraupdate)
6583                         S_ExtraUpdate ();
6584         }
6585
6586         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6587         {
6588                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6589                 if (r_timereport_active)
6590                         R_TimeReport("world");
6591         }
6592
6593         // don't let sound skip if going slow
6594         if (r_refdef.scene.extraupdate)
6595                 S_ExtraUpdate ();
6596
6597         R_DrawModels();
6598         if (r_timereport_active)
6599                 R_TimeReport("models");
6600
6601         // don't let sound skip if going slow
6602         if (r_refdef.scene.extraupdate)
6603                 S_ExtraUpdate ();
6604
6605         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6606         {
6607                 R_DrawModelShadows();
6608                 R_ResetViewRendering3D();
6609                 // don't let sound skip if going slow
6610                 if (r_refdef.scene.extraupdate)
6611                         S_ExtraUpdate ();
6612         }
6613
6614         if (!r_shadow_usingdeferredprepass)
6615         {
6616                 R_Shadow_DrawLights();
6617                 if (r_timereport_active)
6618                         R_TimeReport("rtlights");
6619         }
6620
6621         // don't let sound skip if going slow
6622         if (r_refdef.scene.extraupdate)
6623                 S_ExtraUpdate ();
6624
6625         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6626         {
6627                 R_DrawModelShadows();
6628                 R_ResetViewRendering3D();
6629                 // don't let sound skip if going slow
6630                 if (r_refdef.scene.extraupdate)
6631                         S_ExtraUpdate ();
6632         }
6633
6634         if (cl.csqc_vidvars.drawworld)
6635         {
6636                 if (cl_decals_newsystem.integer)
6637                 {
6638                         R_DrawModelDecals();
6639                         if (r_timereport_active)
6640                                 R_TimeReport("modeldecals");
6641                 }
6642                 else
6643                 {
6644                         R_DrawDecals();
6645                         if (r_timereport_active)
6646                                 R_TimeReport("decals");
6647                 }
6648
6649                 R_DrawParticles();
6650                 if (r_timereport_active)
6651                         R_TimeReport("particles");
6652
6653                 R_DrawExplosions();
6654                 if (r_timereport_active)
6655                         R_TimeReport("explosions");
6656
6657                 R_DrawLightningBeams();
6658                 if (r_timereport_active)
6659                         R_TimeReport("lightning");
6660         }
6661
6662         VM_CL_AddPolygonsToMeshQueue();
6663
6664         if (r_refdef.view.showdebug)
6665         {
6666                 if (cl_locs_show.integer)
6667                 {
6668                         R_DrawLocs();
6669                         if (r_timereport_active)
6670                                 R_TimeReport("showlocs");
6671                 }
6672
6673                 if (r_drawportals.integer)
6674                 {
6675                         R_DrawPortals();
6676                         if (r_timereport_active)
6677                                 R_TimeReport("portals");
6678                 }
6679
6680                 if (r_showbboxes.value > 0)
6681                 {
6682                         R_DrawEntityBBoxes();
6683                         if (r_timereport_active)
6684                                 R_TimeReport("bboxes");
6685                 }
6686         }
6687
6688         R_MeshQueue_RenderTransparent();
6689         if (r_timereport_active)
6690                 R_TimeReport("drawtrans");
6691
6692         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))
6693         {
6694                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6695                 if (r_timereport_active)
6696                         R_TimeReport("worlddebug");
6697                 R_DrawModelsDebug();
6698                 if (r_timereport_active)
6699                         R_TimeReport("modeldebug");
6700         }
6701
6702         if (cl.csqc_vidvars.drawworld)
6703         {
6704                 R_Shadow_DrawCoronas();
6705                 if (r_timereport_active)
6706                         R_TimeReport("coronas");
6707         }
6708
6709 #if 0
6710         {
6711                 GL_DepthTest(false);
6712                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6713                 GL_Color(1, 1, 1, 1);
6714                 qglBegin(GL_POLYGON);
6715                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6716                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6717                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6718                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6719                 qglEnd();
6720                 qglBegin(GL_POLYGON);
6721                 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]);
6722                 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]);
6723                 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]);
6724                 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]);
6725                 qglEnd();
6726                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6727         }
6728 #endif
6729
6730         // don't let sound skip if going slow
6731         if (r_refdef.scene.extraupdate)
6732                 S_ExtraUpdate ();
6733
6734         R_ResetViewRendering2D();
6735 }
6736
6737 static const unsigned short bboxelements[36] =
6738 {
6739         5, 1, 3, 5, 3, 7,
6740         6, 2, 0, 6, 0, 4,
6741         7, 3, 2, 7, 2, 6,
6742         4, 0, 1, 4, 1, 5,
6743         4, 5, 7, 4, 7, 6,
6744         1, 0, 2, 1, 2, 3,
6745 };
6746
6747 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6748 {
6749         int i;
6750         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6751
6752         RSurf_ActiveWorldEntity();
6753
6754         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6755         GL_DepthMask(false);
6756         GL_DepthRange(0, 1);
6757         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6758 //      R_Mesh_ResetTextureState();
6759
6760         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6761         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6762         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6763         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6764         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6765         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6766         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6767         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6768         R_FillColors(color4f, 8, cr, cg, cb, ca);
6769         if (r_refdef.fogenabled)
6770         {
6771                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6772                 {
6773                         f1 = RSurf_FogVertex(v);
6774                         f2 = 1 - f1;
6775                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6776                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6777                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6778                 }
6779         }
6780         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6781         R_Mesh_ResetTextureState();
6782         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6783         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6784 }
6785
6786 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6787 {
6788         int i;
6789         float color[4];
6790         prvm_edict_t *edict;
6791         prvm_prog_t *prog_save = prog;
6792
6793         // this function draws bounding boxes of server entities
6794         if (!sv.active)
6795                 return;
6796
6797         GL_CullFace(GL_NONE);
6798         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6799
6800         prog = 0;
6801         SV_VM_Begin();
6802         for (i = 0;i < numsurfaces;i++)
6803         {
6804                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6805                 switch ((int)edict->fields.server->solid)
6806                 {
6807                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6808                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6809                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6810                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6811                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6812                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6813                 }
6814                 color[3] *= r_showbboxes.value;
6815                 color[3] = bound(0, color[3], 1);
6816                 GL_DepthTest(!r_showdisabledepthtest.integer);
6817                 GL_CullFace(r_refdef.view.cullface_front);
6818                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6819         }
6820         SV_VM_End();
6821         prog = prog_save;
6822 }
6823
6824 static void R_DrawEntityBBoxes(void)
6825 {
6826         int i;
6827         prvm_edict_t *edict;
6828         vec3_t center;
6829         prvm_prog_t *prog_save = prog;
6830
6831         // this function draws bounding boxes of server entities
6832         if (!sv.active)
6833                 return;
6834
6835         prog = 0;
6836         SV_VM_Begin();
6837         for (i = 0;i < prog->num_edicts;i++)
6838         {
6839                 edict = PRVM_EDICT_NUM(i);
6840                 if (edict->priv.server->free)
6841                         continue;
6842                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6843                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6844                         continue;
6845                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6846                         continue;
6847                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6848                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6849         }
6850         SV_VM_End();
6851         prog = prog_save;
6852 }
6853
6854 static const int nomodelelement3i[24] =
6855 {
6856         5, 2, 0,
6857         5, 1, 2,
6858         5, 0, 3,
6859         5, 3, 1,
6860         0, 2, 4,
6861         2, 1, 4,
6862         3, 0, 4,
6863         1, 3, 4
6864 };
6865
6866 static const unsigned short nomodelelement3s[24] =
6867 {
6868         5, 2, 0,
6869         5, 1, 2,
6870         5, 0, 3,
6871         5, 3, 1,
6872         0, 2, 4,
6873         2, 1, 4,
6874         3, 0, 4,
6875         1, 3, 4
6876 };
6877
6878 static const float nomodelvertex3f[6*3] =
6879 {
6880         -16,   0,   0,
6881          16,   0,   0,
6882           0, -16,   0,
6883           0,  16,   0,
6884           0,   0, -16,
6885           0,   0,  16
6886 };
6887
6888 static const float nomodelcolor4f[6*4] =
6889 {
6890         0.0f, 0.0f, 0.5f, 1.0f,
6891         0.0f, 0.0f, 0.5f, 1.0f,
6892         0.0f, 0.5f, 0.0f, 1.0f,
6893         0.0f, 0.5f, 0.0f, 1.0f,
6894         0.5f, 0.0f, 0.0f, 1.0f,
6895         0.5f, 0.0f, 0.0f, 1.0f
6896 };
6897
6898 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6899 {
6900         int i;
6901         float f1, f2, *c;
6902         float color4f[6*4];
6903
6904         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);
6905
6906         // this is only called once per entity so numsurfaces is always 1, and
6907         // surfacelist is always {0}, so this code does not handle batches
6908
6909         if (rsurface.ent_flags & RENDER_ADDITIVE)
6910         {
6911                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6912                 GL_DepthMask(false);
6913         }
6914         else if (rsurface.colormod[3] < 1)
6915         {
6916                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6917                 GL_DepthMask(false);
6918         }
6919         else
6920         {
6921                 GL_BlendFunc(GL_ONE, GL_ZERO);
6922                 GL_DepthMask(true);
6923         }
6924         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6925         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6926         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6927         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6928         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6929         for (i = 0, c = color4f;i < 6;i++, c += 4)
6930         {
6931                 c[0] *= rsurface.colormod[0];
6932                 c[1] *= rsurface.colormod[1];
6933                 c[2] *= rsurface.colormod[2];
6934                 c[3] *= rsurface.colormod[3];
6935         }
6936         if (r_refdef.fogenabled)
6937         {
6938                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6939                 {
6940                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6941                         f2 = 1 - f1;
6942                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6943                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6944                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6945                 }
6946         }
6947 //      R_Mesh_ResetTextureState();
6948         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6949         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6950         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6951 }
6952
6953 void R_DrawNoModel(entity_render_t *ent)
6954 {
6955         vec3_t org;
6956         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6957         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6958                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6959         else
6960                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6961 }
6962
6963 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6964 {
6965         vec3_t right1, right2, diff, normal;
6966
6967         VectorSubtract (org2, org1, normal);
6968
6969         // calculate 'right' vector for start
6970         VectorSubtract (r_refdef.view.origin, org1, diff);
6971         CrossProduct (normal, diff, right1);
6972         VectorNormalize (right1);
6973
6974         // calculate 'right' vector for end
6975         VectorSubtract (r_refdef.view.origin, org2, diff);
6976         CrossProduct (normal, diff, right2);
6977         VectorNormalize (right2);
6978
6979         vert[ 0] = org1[0] + width * right1[0];
6980         vert[ 1] = org1[1] + width * right1[1];
6981         vert[ 2] = org1[2] + width * right1[2];
6982         vert[ 3] = org1[0] - width * right1[0];
6983         vert[ 4] = org1[1] - width * right1[1];
6984         vert[ 5] = org1[2] - width * right1[2];
6985         vert[ 6] = org2[0] - width * right2[0];
6986         vert[ 7] = org2[1] - width * right2[1];
6987         vert[ 8] = org2[2] - width * right2[2];
6988         vert[ 9] = org2[0] + width * right2[0];
6989         vert[10] = org2[1] + width * right2[1];
6990         vert[11] = org2[2] + width * right2[2];
6991 }
6992
6993 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)
6994 {
6995         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6996         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6997         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6998         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6999         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7000         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7001         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7002         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7003         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7004         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7005         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7006         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7007 }
7008
7009 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7010 {
7011         int i;
7012         float *vertex3f;
7013         float v[3];
7014         VectorSet(v, x, y, z);
7015         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7016                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7017                         break;
7018         if (i == mesh->numvertices)
7019         {
7020                 if (mesh->numvertices < mesh->maxvertices)
7021                 {
7022                         VectorCopy(v, vertex3f);
7023                         mesh->numvertices++;
7024                 }
7025                 return mesh->numvertices;
7026         }
7027         else
7028                 return i;
7029 }
7030
7031 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7032 {
7033         int i;
7034         int *e, element[3];
7035         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7036         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7037         e = mesh->element3i + mesh->numtriangles * 3;
7038         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7039         {
7040                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7041                 if (mesh->numtriangles < mesh->maxtriangles)
7042                 {
7043                         *e++ = element[0];
7044                         *e++ = element[1];
7045                         *e++ = element[2];
7046                         mesh->numtriangles++;
7047                 }
7048                 element[1] = element[2];
7049         }
7050 }
7051
7052 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7053 {
7054         int i;
7055         int *e, element[3];
7056         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7057         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7058         e = mesh->element3i + mesh->numtriangles * 3;
7059         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7060         {
7061                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7062                 if (mesh->numtriangles < mesh->maxtriangles)
7063                 {
7064                         *e++ = element[0];
7065                         *e++ = element[1];
7066                         *e++ = element[2];
7067                         mesh->numtriangles++;
7068                 }
7069                 element[1] = element[2];
7070         }
7071 }
7072
7073 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7074 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7075 {
7076         int planenum, planenum2;
7077         int w;
7078         int tempnumpoints;
7079         mplane_t *plane, *plane2;
7080         double maxdist;
7081         double temppoints[2][256*3];
7082         // figure out how large a bounding box we need to properly compute this brush
7083         maxdist = 0;
7084         for (w = 0;w < numplanes;w++)
7085                 maxdist = max(maxdist, fabs(planes[w].dist));
7086         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7087         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7088         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7089         {
7090                 w = 0;
7091                 tempnumpoints = 4;
7092                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7093                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7094                 {
7095                         if (planenum2 == planenum)
7096                                 continue;
7097                         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);
7098                         w = !w;
7099                 }
7100                 if (tempnumpoints < 3)
7101                         continue;
7102                 // generate elements forming a triangle fan for this polygon
7103                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7104         }
7105 }
7106
7107 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)
7108 {
7109         texturelayer_t *layer;
7110         layer = t->currentlayers + t->currentnumlayers++;
7111         layer->type = type;
7112         layer->depthmask = depthmask;
7113         layer->blendfunc1 = blendfunc1;
7114         layer->blendfunc2 = blendfunc2;
7115         layer->texture = texture;
7116         layer->texmatrix = *matrix;
7117         layer->color[0] = r;
7118         layer->color[1] = g;
7119         layer->color[2] = b;
7120         layer->color[3] = a;
7121 }
7122
7123 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7124 {
7125         if(parms[0] == 0 && parms[1] == 0)
7126                 return false;
7127         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7128                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7129                         return false;
7130         return true;
7131 }
7132
7133 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7134 {
7135         double index, f;
7136         index = parms[2] + r_refdef.scene.time * parms[3];
7137         index -= floor(index);
7138         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7139         {
7140         default:
7141         case Q3WAVEFUNC_NONE:
7142         case Q3WAVEFUNC_NOISE:
7143         case Q3WAVEFUNC_COUNT:
7144                 f = 0;
7145                 break;
7146         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7147         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7148         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7149         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7150         case Q3WAVEFUNC_TRIANGLE:
7151                 index *= 4;
7152                 f = index - floor(index);
7153                 if (index < 1)
7154                         f = f;
7155                 else if (index < 2)
7156                         f = 1 - f;
7157                 else if (index < 3)
7158                         f = -f;
7159                 else
7160                         f = -(1 - f);
7161                 break;
7162         }
7163         f = parms[0] + parms[1] * f;
7164         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7165                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7166         return (float) f;
7167 }
7168
7169 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7170 {
7171         int w, h, idx;
7172         float f;
7173         float tcmat[12];
7174         matrix4x4_t matrix, temp;
7175         switch(tcmod->tcmod)
7176         {
7177                 case Q3TCMOD_COUNT:
7178                 case Q3TCMOD_NONE:
7179                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7180                                 matrix = r_waterscrollmatrix;
7181                         else
7182                                 matrix = identitymatrix;
7183                         break;
7184                 case Q3TCMOD_ENTITYTRANSLATE:
7185                         // this is used in Q3 to allow the gamecode to control texcoord
7186                         // scrolling on the entity, which is not supported in darkplaces yet.
7187                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7188                         break;
7189                 case Q3TCMOD_ROTATE:
7190                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7191                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7192                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7193                         break;
7194                 case Q3TCMOD_SCALE:
7195                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7196                         break;
7197                 case Q3TCMOD_SCROLL:
7198                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7199                         break;
7200                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7201                         w = (int) tcmod->parms[0];
7202                         h = (int) tcmod->parms[1];
7203                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7204                         f = f - floor(f);
7205                         idx = (int) floor(f * w * h);
7206                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7207                         break;
7208                 case Q3TCMOD_STRETCH:
7209                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7210                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7211                         break;
7212                 case Q3TCMOD_TRANSFORM:
7213                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7214                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7215                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7216                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7217                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7218                         break;
7219                 case Q3TCMOD_TURBULENT:
7220                         // this is handled in the RSurf_PrepareVertices function
7221                         matrix = identitymatrix;
7222                         break;
7223         }
7224         temp = *texmatrix;
7225         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7226 }
7227
7228 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7229 {
7230         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7231         char name[MAX_QPATH];
7232         skinframe_t *skinframe;
7233         unsigned char pixels[296*194];
7234         strlcpy(cache->name, skinname, sizeof(cache->name));
7235         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7236         if (developer_loading.integer)
7237                 Con_Printf("loading %s\n", name);
7238         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7239         if (!skinframe || !skinframe->base)
7240         {
7241                 unsigned char *f;
7242                 fs_offset_t filesize;
7243                 skinframe = NULL;
7244                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7245                 if (f)
7246                 {
7247                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7248                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7249                         Mem_Free(f);
7250                 }
7251         }
7252         cache->skinframe = skinframe;
7253 }
7254
7255 texture_t *R_GetCurrentTexture(texture_t *t)
7256 {
7257         int i;
7258         const entity_render_t *ent = rsurface.entity;
7259         dp_model_t *model = ent->model;
7260         q3shaderinfo_layer_tcmod_t *tcmod;
7261
7262         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7263                 return t->currentframe;
7264         t->update_lastrenderframe = r_textureframe;
7265         t->update_lastrenderentity = (void *)ent;
7266
7267         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7268                 t->camera_entity = ent->entitynumber;
7269         else
7270                 t->camera_entity = 0;
7271
7272         // switch to an alternate material if this is a q1bsp animated material
7273         {
7274                 texture_t *texture = t;
7275                 int s = rsurface.ent_skinnum;
7276                 if ((unsigned int)s >= (unsigned int)model->numskins)
7277                         s = 0;
7278                 if (model->skinscenes)
7279                 {
7280                         if (model->skinscenes[s].framecount > 1)
7281                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7282                         else
7283                                 s = model->skinscenes[s].firstframe;
7284                 }
7285                 if (s > 0)
7286                         t = t + s * model->num_surfaces;
7287                 if (t->animated)
7288                 {
7289                         // use an alternate animation if the entity's frame is not 0,
7290                         // and only if the texture has an alternate animation
7291                         if (rsurface.ent_alttextures && t->anim_total[1])
7292                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7293                         else
7294                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7295                 }
7296                 texture->currentframe = t;
7297         }
7298
7299         // update currentskinframe to be a qw skin or animation frame
7300         if (rsurface.ent_qwskin >= 0)
7301         {
7302                 i = rsurface.ent_qwskin;
7303                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7304                 {
7305                         r_qwskincache_size = cl.maxclients;
7306                         if (r_qwskincache)
7307                                 Mem_Free(r_qwskincache);
7308                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7309                 }
7310                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7311                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7312                 t->currentskinframe = r_qwskincache[i].skinframe;
7313                 if (t->currentskinframe == NULL)
7314                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7315         }
7316         else if (t->numskinframes >= 2)
7317                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7318         if (t->backgroundnumskinframes >= 2)
7319                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7320
7321         t->currentmaterialflags = t->basematerialflags;
7322         t->currentalpha = rsurface.colormod[3];
7323         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7324                 t->currentalpha *= r_wateralpha.value;
7325         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7326                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7327         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7328                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7329         if (!(rsurface.ent_flags & RENDER_LIGHT))
7330                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7331         else if (FAKELIGHT_ENABLED)
7332         {
7333                         // no modellight if using fakelight for the map
7334         }
7335         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7336         {
7337                 // pick a model lighting mode
7338                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7339                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7340                 else
7341                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7342         }
7343         if (rsurface.ent_flags & RENDER_ADDITIVE)
7344                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7345         else if (t->currentalpha < 1)
7346                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7347         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7348                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7349         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7350                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7351         if (t->backgroundnumskinframes)
7352                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7353         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7354         {
7355                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7356                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7357         }
7358         else
7359                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7360         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7361                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7362
7363         // there is no tcmod
7364         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7365         {
7366                 t->currenttexmatrix = r_waterscrollmatrix;
7367                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7368         }
7369         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7370         {
7371                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7372                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7373         }
7374
7375         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7376                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7377         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7378                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7379
7380         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7381         if (t->currentskinframe->qpixels)
7382                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7383         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7384         if (!t->basetexture)
7385                 t->basetexture = r_texture_notexture;
7386         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7387         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7388         t->nmaptexture = t->currentskinframe->nmap;
7389         if (!t->nmaptexture)
7390                 t->nmaptexture = r_texture_blanknormalmap;
7391         t->glosstexture = r_texture_black;
7392         t->glowtexture = t->currentskinframe->glow;
7393         t->fogtexture = t->currentskinframe->fog;
7394         t->reflectmasktexture = t->currentskinframe->reflect;
7395         if (t->backgroundnumskinframes)
7396         {
7397                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7398                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7399                 t->backgroundglosstexture = r_texture_black;
7400                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7401                 if (!t->backgroundnmaptexture)
7402                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7403         }
7404         else
7405         {
7406                 t->backgroundbasetexture = r_texture_white;
7407                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7408                 t->backgroundglosstexture = r_texture_black;
7409                 t->backgroundglowtexture = NULL;
7410         }
7411         t->specularpower = r_shadow_glossexponent.value;
7412         // TODO: store reference values for these in the texture?
7413         t->specularscale = 0;
7414         if (r_shadow_gloss.integer > 0)
7415         {
7416                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7417                 {
7418                         if (r_shadow_glossintensity.value > 0)
7419                         {
7420                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7421                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7422                                 t->specularscale = r_shadow_glossintensity.value;
7423                         }
7424                 }
7425                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7426                 {
7427                         t->glosstexture = r_texture_white;
7428                         t->backgroundglosstexture = r_texture_white;
7429                         t->specularscale = r_shadow_gloss2intensity.value;
7430                         t->specularpower = r_shadow_gloss2exponent.value;
7431                 }
7432         }
7433         t->specularscale *= t->specularscalemod;
7434         t->specularpower *= t->specularpowermod;
7435
7436         // lightmaps mode looks bad with dlights using actual texturing, so turn
7437         // off the colormap and glossmap, but leave the normalmap on as it still
7438         // accurately represents the shading involved
7439         if (gl_lightmaps.integer)
7440         {
7441                 t->basetexture = r_texture_grey128;
7442                 t->pantstexture = r_texture_black;
7443                 t->shirttexture = r_texture_black;
7444                 t->nmaptexture = r_texture_blanknormalmap;
7445                 t->glosstexture = r_texture_black;
7446                 t->glowtexture = NULL;
7447                 t->fogtexture = NULL;
7448                 t->reflectmasktexture = NULL;
7449                 t->backgroundbasetexture = NULL;
7450                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7451                 t->backgroundglosstexture = r_texture_black;
7452                 t->backgroundglowtexture = NULL;
7453                 t->specularscale = 0;
7454                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7455         }
7456
7457         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7458         VectorClear(t->dlightcolor);
7459         t->currentnumlayers = 0;
7460         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7461         {
7462                 int blendfunc1, blendfunc2;
7463                 qboolean depthmask;
7464                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7465                 {
7466                         blendfunc1 = GL_SRC_ALPHA;
7467                         blendfunc2 = GL_ONE;
7468                 }
7469                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7470                 {
7471                         blendfunc1 = GL_SRC_ALPHA;
7472                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7473                 }
7474                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7475                 {
7476                         blendfunc1 = t->customblendfunc[0];
7477                         blendfunc2 = t->customblendfunc[1];
7478                 }
7479                 else
7480                 {
7481                         blendfunc1 = GL_ONE;
7482                         blendfunc2 = GL_ZERO;
7483                 }
7484                 // don't colormod evilblend textures
7485                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7486                         VectorSet(t->lightmapcolor, 1, 1, 1);
7487                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7488                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7489                 {
7490                         // fullbright is not affected by r_refdef.lightmapintensity
7491                         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]);
7492                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7493                                 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]);
7494                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7495                                 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]);
7496                 }
7497                 else
7498                 {
7499                         vec3_t ambientcolor;
7500                         float colorscale;
7501                         // set the color tint used for lights affecting this surface
7502                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7503                         colorscale = 2;
7504                         // q3bsp has no lightmap updates, so the lightstylevalue that
7505                         // would normally be baked into the lightmap must be
7506                         // applied to the color
7507                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7508                         if (model->type == mod_brushq3)
7509                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7510                         colorscale *= r_refdef.lightmapintensity;
7511                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7512                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7513                         // basic lit geometry
7514                         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]);
7515                         // add pants/shirt if needed
7516                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7517                                 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]);
7518                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7519                                 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]);
7520                         // now add ambient passes if needed
7521                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7522                         {
7523                                 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]);
7524                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7525                                         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]);
7526                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7527                                         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]);
7528                         }
7529                 }
7530                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7531                         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]);
7532                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7533                 {
7534                         // if this is opaque use alpha blend which will darken the earlier
7535                         // passes cheaply.
7536                         //
7537                         // if this is an alpha blended material, all the earlier passes
7538                         // were darkened by fog already, so we only need to add the fog
7539                         // color ontop through the fog mask texture
7540                         //
7541                         // if this is an additive blended material, all the earlier passes
7542                         // were darkened by fog already, and we should not add fog color
7543                         // (because the background was not darkened, there is no fog color
7544                         // that was lost behind it).
7545                         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]);
7546                 }
7547         }
7548
7549         return t->currentframe;
7550 }
7551
7552 rsurfacestate_t rsurface;
7553
7554 void RSurf_ActiveWorldEntity(void)
7555 {
7556         dp_model_t *model = r_refdef.scene.worldmodel;
7557         //if (rsurface.entity == r_refdef.scene.worldentity)
7558         //      return;
7559         rsurface.entity = r_refdef.scene.worldentity;
7560         rsurface.skeleton = NULL;
7561         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7562         rsurface.ent_skinnum = 0;
7563         rsurface.ent_qwskin = -1;
7564         rsurface.ent_shadertime = 0;
7565         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7566         rsurface.matrix = identitymatrix;
7567         rsurface.inversematrix = identitymatrix;
7568         rsurface.matrixscale = 1;
7569         rsurface.inversematrixscale = 1;
7570         R_EntityMatrix(&identitymatrix);
7571         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7572         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7573         rsurface.fograngerecip = r_refdef.fograngerecip;
7574         rsurface.fogheightfade = r_refdef.fogheightfade;
7575         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7576         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7577         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7578         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7579         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7580         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7581         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7582         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7583         rsurface.colormod[3] = 1;
7584         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);
7585         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7586         rsurface.frameblend[0].lerp = 1;
7587         rsurface.ent_alttextures = false;
7588         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7589         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7590         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7591         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7592         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7593         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7594         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7595         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7596         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7597         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7598         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7599         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7600         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7601         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7602         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7603         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7604         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7605         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7606         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7607         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7608         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7609         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7610         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7611         rsurface.modelelement3i = model->surfmesh.data_element3i;
7612         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7613         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7614         rsurface.modelelement3s = model->surfmesh.data_element3s;
7615         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7616         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7617         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7618         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7619         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7620         rsurface.modelsurfaces = model->data_surfaces;
7621         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7622         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7623         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7624         rsurface.modelgeneratedvertex = false;
7625         rsurface.batchgeneratedvertex = false;
7626         rsurface.batchfirstvertex = 0;
7627         rsurface.batchnumvertices = 0;
7628         rsurface.batchfirsttriangle = 0;
7629         rsurface.batchnumtriangles = 0;
7630         rsurface.batchvertex3f  = NULL;
7631         rsurface.batchvertex3f_vertexbuffer = NULL;
7632         rsurface.batchvertex3f_bufferoffset = 0;
7633         rsurface.batchsvector3f = NULL;
7634         rsurface.batchsvector3f_vertexbuffer = NULL;
7635         rsurface.batchsvector3f_bufferoffset = 0;
7636         rsurface.batchtvector3f = NULL;
7637         rsurface.batchtvector3f_vertexbuffer = NULL;
7638         rsurface.batchtvector3f_bufferoffset = 0;
7639         rsurface.batchnormal3f  = NULL;
7640         rsurface.batchnormal3f_vertexbuffer = NULL;
7641         rsurface.batchnormal3f_bufferoffset = 0;
7642         rsurface.batchlightmapcolor4f = NULL;
7643         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7644         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7645         rsurface.batchtexcoordtexture2f = NULL;
7646         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7647         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7648         rsurface.batchtexcoordlightmap2f = NULL;
7649         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7650         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7651         rsurface.batchvertexmesh = NULL;
7652         rsurface.batchvertexmeshbuffer = NULL;
7653         rsurface.batchvertex3fbuffer = NULL;
7654         rsurface.batchelement3i = NULL;
7655         rsurface.batchelement3i_indexbuffer = NULL;
7656         rsurface.batchelement3i_bufferoffset = 0;
7657         rsurface.batchelement3s = NULL;
7658         rsurface.batchelement3s_indexbuffer = NULL;
7659         rsurface.batchelement3s_bufferoffset = 0;
7660         rsurface.passcolor4f = NULL;
7661         rsurface.passcolor4f_vertexbuffer = NULL;
7662         rsurface.passcolor4f_bufferoffset = 0;
7663 }
7664
7665 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7666 {
7667         dp_model_t *model = ent->model;
7668         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7669         //      return;
7670         rsurface.entity = (entity_render_t *)ent;
7671         rsurface.skeleton = ent->skeleton;
7672         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7673         rsurface.ent_skinnum = ent->skinnum;
7674         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;
7675         rsurface.ent_shadertime = ent->shadertime;
7676         rsurface.ent_flags = ent->flags;
7677         rsurface.matrix = ent->matrix;
7678         rsurface.inversematrix = ent->inversematrix;
7679         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7680         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7681         R_EntityMatrix(&rsurface.matrix);
7682         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7683         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7684         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7685         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7686         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7687         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7688         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7689         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7690         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7691         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7692         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7693         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7694         rsurface.colormod[3] = ent->alpha;
7695         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7696         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7697         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7698         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7699         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7700         if (ent->model->brush.submodel && !prepass)
7701         {
7702                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7703                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7704         }
7705         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7706         {
7707                 if (ent->animcache_vertex3f)
7708                 {
7709                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7710                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7711                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7712                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7713                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7714                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7715                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7716                 }
7717                 else if (wanttangents)
7718                 {
7719                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7720                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7721                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7722                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7723                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7724                         rsurface.modelvertexmesh = NULL;
7725                         rsurface.modelvertexmeshbuffer = NULL;
7726                         rsurface.modelvertex3fbuffer = NULL;
7727                 }
7728                 else if (wantnormals)
7729                 {
7730                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7731                         rsurface.modelsvector3f = NULL;
7732                         rsurface.modeltvector3f = NULL;
7733                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7734                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7735                         rsurface.modelvertexmesh = NULL;
7736                         rsurface.modelvertexmeshbuffer = NULL;
7737                         rsurface.modelvertex3fbuffer = NULL;
7738                 }
7739                 else
7740                 {
7741                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7742                         rsurface.modelsvector3f = NULL;
7743                         rsurface.modeltvector3f = NULL;
7744                         rsurface.modelnormal3f = NULL;
7745                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7746                         rsurface.modelvertexmesh = NULL;
7747                         rsurface.modelvertexmeshbuffer = NULL;
7748                         rsurface.modelvertex3fbuffer = NULL;
7749                 }
7750                 rsurface.modelvertex3f_vertexbuffer = 0;
7751                 rsurface.modelvertex3f_bufferoffset = 0;
7752                 rsurface.modelsvector3f_vertexbuffer = 0;
7753                 rsurface.modelsvector3f_bufferoffset = 0;
7754                 rsurface.modeltvector3f_vertexbuffer = 0;
7755                 rsurface.modeltvector3f_bufferoffset = 0;
7756                 rsurface.modelnormal3f_vertexbuffer = 0;
7757                 rsurface.modelnormal3f_bufferoffset = 0;
7758                 rsurface.modelgeneratedvertex = true;
7759         }
7760         else
7761         {
7762                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7763                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7764                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7765                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7766                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7767                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7768                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7769                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7770                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7771                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7772                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7773                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7774                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7775                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7776                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7777                 rsurface.modelgeneratedvertex = false;
7778         }
7779         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7780         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7781         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7782         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7783         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7784         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7785         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7786         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7787         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7788         rsurface.modelelement3i = model->surfmesh.data_element3i;
7789         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7790         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7791         rsurface.modelelement3s = model->surfmesh.data_element3s;
7792         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7793         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7794         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7795         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7796         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7797         rsurface.modelsurfaces = model->data_surfaces;
7798         rsurface.batchgeneratedvertex = false;
7799         rsurface.batchfirstvertex = 0;
7800         rsurface.batchnumvertices = 0;
7801         rsurface.batchfirsttriangle = 0;
7802         rsurface.batchnumtriangles = 0;
7803         rsurface.batchvertex3f  = NULL;
7804         rsurface.batchvertex3f_vertexbuffer = NULL;
7805         rsurface.batchvertex3f_bufferoffset = 0;
7806         rsurface.batchsvector3f = NULL;
7807         rsurface.batchsvector3f_vertexbuffer = NULL;
7808         rsurface.batchsvector3f_bufferoffset = 0;
7809         rsurface.batchtvector3f = NULL;
7810         rsurface.batchtvector3f_vertexbuffer = NULL;
7811         rsurface.batchtvector3f_bufferoffset = 0;
7812         rsurface.batchnormal3f  = NULL;
7813         rsurface.batchnormal3f_vertexbuffer = NULL;
7814         rsurface.batchnormal3f_bufferoffset = 0;
7815         rsurface.batchlightmapcolor4f = NULL;
7816         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7817         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7818         rsurface.batchtexcoordtexture2f = NULL;
7819         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7820         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7821         rsurface.batchtexcoordlightmap2f = NULL;
7822         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7823         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7824         rsurface.batchvertexmesh = NULL;
7825         rsurface.batchvertexmeshbuffer = NULL;
7826         rsurface.batchvertex3fbuffer = NULL;
7827         rsurface.batchelement3i = NULL;
7828         rsurface.batchelement3i_indexbuffer = NULL;
7829         rsurface.batchelement3i_bufferoffset = 0;
7830         rsurface.batchelement3s = NULL;
7831         rsurface.batchelement3s_indexbuffer = NULL;
7832         rsurface.batchelement3s_bufferoffset = 0;
7833         rsurface.passcolor4f = NULL;
7834         rsurface.passcolor4f_vertexbuffer = NULL;
7835         rsurface.passcolor4f_bufferoffset = 0;
7836 }
7837
7838 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)
7839 {
7840         rsurface.entity = r_refdef.scene.worldentity;
7841         rsurface.skeleton = NULL;
7842         rsurface.ent_skinnum = 0;
7843         rsurface.ent_qwskin = -1;
7844         rsurface.ent_shadertime = shadertime;
7845         rsurface.ent_flags = entflags;
7846         rsurface.modelnumvertices = numvertices;
7847         rsurface.modelnumtriangles = numtriangles;
7848         rsurface.matrix = *matrix;
7849         rsurface.inversematrix = *inversematrix;
7850         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7851         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7852         R_EntityMatrix(&rsurface.matrix);
7853         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7854         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7855         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7856         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7857         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7858         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7859         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7860         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7861         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7862         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7863         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7864         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7865         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);
7866         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7867         rsurface.frameblend[0].lerp = 1;
7868         rsurface.ent_alttextures = false;
7869         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7870         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7871         if (wanttangents)
7872         {
7873                 rsurface.modelvertex3f = (float *)vertex3f;
7874                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7875                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7876                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7877         }
7878         else if (wantnormals)
7879         {
7880                 rsurface.modelvertex3f = (float *)vertex3f;
7881                 rsurface.modelsvector3f = NULL;
7882                 rsurface.modeltvector3f = NULL;
7883                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7884         }
7885         else
7886         {
7887                 rsurface.modelvertex3f = (float *)vertex3f;
7888                 rsurface.modelsvector3f = NULL;
7889                 rsurface.modeltvector3f = NULL;
7890                 rsurface.modelnormal3f = NULL;
7891         }
7892         rsurface.modelvertexmesh = NULL;
7893         rsurface.modelvertexmeshbuffer = NULL;
7894         rsurface.modelvertex3fbuffer = NULL;
7895         rsurface.modelvertex3f_vertexbuffer = 0;
7896         rsurface.modelvertex3f_bufferoffset = 0;
7897         rsurface.modelsvector3f_vertexbuffer = 0;
7898         rsurface.modelsvector3f_bufferoffset = 0;
7899         rsurface.modeltvector3f_vertexbuffer = 0;
7900         rsurface.modeltvector3f_bufferoffset = 0;
7901         rsurface.modelnormal3f_vertexbuffer = 0;
7902         rsurface.modelnormal3f_bufferoffset = 0;
7903         rsurface.modelgeneratedvertex = true;
7904         rsurface.modellightmapcolor4f  = (float *)color4f;
7905         rsurface.modellightmapcolor4f_vertexbuffer = 0;
7906         rsurface.modellightmapcolor4f_bufferoffset = 0;
7907         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
7908         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7909         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7910         rsurface.modeltexcoordlightmap2f  = NULL;
7911         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7912         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7913         rsurface.modelelement3i = (int *)element3i;
7914         rsurface.modelelement3i_indexbuffer = NULL;
7915         rsurface.modelelement3i_bufferoffset = 0;
7916         rsurface.modelelement3s = (unsigned short *)element3s;
7917         rsurface.modelelement3s_indexbuffer = NULL;
7918         rsurface.modelelement3s_bufferoffset = 0;
7919         rsurface.modellightmapoffsets = NULL;
7920         rsurface.modelsurfaces = NULL;
7921         rsurface.batchgeneratedvertex = false;
7922         rsurface.batchfirstvertex = 0;
7923         rsurface.batchnumvertices = 0;
7924         rsurface.batchfirsttriangle = 0;
7925         rsurface.batchnumtriangles = 0;
7926         rsurface.batchvertex3f  = NULL;
7927         rsurface.batchvertex3f_vertexbuffer = NULL;
7928         rsurface.batchvertex3f_bufferoffset = 0;
7929         rsurface.batchsvector3f = NULL;
7930         rsurface.batchsvector3f_vertexbuffer = NULL;
7931         rsurface.batchsvector3f_bufferoffset = 0;
7932         rsurface.batchtvector3f = NULL;
7933         rsurface.batchtvector3f_vertexbuffer = NULL;
7934         rsurface.batchtvector3f_bufferoffset = 0;
7935         rsurface.batchnormal3f  = NULL;
7936         rsurface.batchnormal3f_vertexbuffer = NULL;
7937         rsurface.batchnormal3f_bufferoffset = 0;
7938         rsurface.batchlightmapcolor4f = NULL;
7939         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7940         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7941         rsurface.batchtexcoordtexture2f = NULL;
7942         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7943         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7944         rsurface.batchtexcoordlightmap2f = NULL;
7945         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7946         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7947         rsurface.batchvertexmesh = NULL;
7948         rsurface.batchvertexmeshbuffer = NULL;
7949         rsurface.batchvertex3fbuffer = NULL;
7950         rsurface.batchelement3i = NULL;
7951         rsurface.batchelement3i_indexbuffer = NULL;
7952         rsurface.batchelement3i_bufferoffset = 0;
7953         rsurface.batchelement3s = NULL;
7954         rsurface.batchelement3s_indexbuffer = NULL;
7955         rsurface.batchelement3s_bufferoffset = 0;
7956         rsurface.passcolor4f = NULL;
7957         rsurface.passcolor4f_vertexbuffer = NULL;
7958         rsurface.passcolor4f_bufferoffset = 0;
7959
7960         if (rsurface.modelnumvertices && rsurface.modelelement3i)
7961         {
7962                 if ((wantnormals || wanttangents) && !normal3f)
7963                 {
7964                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7965                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7966                 }
7967                 if (wanttangents && !svector3f)
7968                 {
7969                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7970                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7971                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7972                 }
7973         }
7974 }
7975
7976 float RSurf_FogPoint(const float *v)
7977 {
7978         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7979         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7980         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7981         float FogHeightFade = r_refdef.fogheightfade;
7982         float fogfrac;
7983         unsigned int fogmasktableindex;
7984         if (r_refdef.fogplaneviewabove)
7985                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7986         else
7987                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7988         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7989         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7990 }
7991
7992 float RSurf_FogVertex(const float *v)
7993 {
7994         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7995         float FogPlaneViewDist = rsurface.fogplaneviewdist;
7996         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7997         float FogHeightFade = rsurface.fogheightfade;
7998         float fogfrac;
7999         unsigned int fogmasktableindex;
8000         if (r_refdef.fogplaneviewabove)
8001                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8002         else
8003                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8004         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8005         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8006 }
8007
8008 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8009 {
8010         int i;
8011         for (i = 0;i < numelements;i++)
8012                 outelement3i[i] = inelement3i[i] + adjust;
8013 }
8014
8015 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8016 extern cvar_t gl_vbo;
8017 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8018 {
8019         int deformindex;
8020         int firsttriangle;
8021         int numtriangles;
8022         int firstvertex;
8023         int endvertex;
8024         int numvertices;
8025         int surfacefirsttriangle;
8026         int surfacenumtriangles;
8027         int surfacefirstvertex;
8028         int surfaceendvertex;
8029         int surfacenumvertices;
8030         int batchnumvertices;
8031         int batchnumtriangles;
8032         int needsupdate;
8033         int i, j;
8034         qboolean gaps;
8035         qboolean dynamicvertex;
8036         float amplitude;
8037         float animpos;
8038         float scale;
8039         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8040         float waveparms[4];
8041         q3shaderinfo_deform_t *deform;
8042         const msurface_t *surface, *firstsurface;
8043         r_vertexmesh_t *vertexmesh;
8044         if (!texturenumsurfaces)
8045                 return;
8046         // find vertex range of this surface batch
8047         gaps = false;
8048         firstsurface = texturesurfacelist[0];
8049         firsttriangle = firstsurface->num_firsttriangle;
8050         batchnumvertices = 0;
8051         batchnumtriangles = 0;
8052         firstvertex = endvertex = firstsurface->num_firstvertex;
8053         for (i = 0;i < texturenumsurfaces;i++)
8054         {
8055                 surface = texturesurfacelist[i];
8056                 if (surface != firstsurface + i)
8057                         gaps = true;
8058                 surfacefirstvertex = surface->num_firstvertex;
8059                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8060                 surfacenumvertices = surface->num_vertices;
8061                 surfacenumtriangles = surface->num_triangles;
8062                 if (firstvertex > surfacefirstvertex)
8063                         firstvertex = surfacefirstvertex;
8064                 if (endvertex < surfaceendvertex)
8065                         endvertex = surfaceendvertex;
8066                 batchnumvertices += surfacenumvertices;
8067                 batchnumtriangles += surfacenumtriangles;
8068         }
8069
8070         // we now know the vertex range used, and if there are any gaps in it
8071         rsurface.batchfirstvertex = firstvertex;
8072         rsurface.batchnumvertices = endvertex - firstvertex;
8073         rsurface.batchfirsttriangle = firsttriangle;
8074         rsurface.batchnumtriangles = batchnumtriangles;
8075
8076         // this variable holds flags for which properties have been updated that
8077         // may require regenerating vertexmesh array...
8078         needsupdate = 0;
8079
8080         // check if any dynamic vertex processing must occur
8081         dynamicvertex = false;
8082
8083         // if there is a chance of animated vertex colors, it's a dynamic batch
8084         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8085         {
8086                 dynamicvertex = true;
8087                 batchneed |= BATCHNEED_NOGAPS;
8088                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8089         }
8090
8091         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8092         {
8093                 switch (deform->deform)
8094                 {
8095                 default:
8096                 case Q3DEFORM_PROJECTIONSHADOW:
8097                 case Q3DEFORM_TEXT0:
8098                 case Q3DEFORM_TEXT1:
8099                 case Q3DEFORM_TEXT2:
8100                 case Q3DEFORM_TEXT3:
8101                 case Q3DEFORM_TEXT4:
8102                 case Q3DEFORM_TEXT5:
8103                 case Q3DEFORM_TEXT6:
8104                 case Q3DEFORM_TEXT7:
8105                 case Q3DEFORM_NONE:
8106                         break;
8107                 case Q3DEFORM_AUTOSPRITE:
8108                         dynamicvertex = true;
8109                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8110                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8111                         break;
8112                 case Q3DEFORM_AUTOSPRITE2:
8113                         dynamicvertex = true;
8114                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8115                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8116                         break;
8117                 case Q3DEFORM_NORMAL:
8118                         dynamicvertex = true;
8119                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8120                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8121                         break;
8122                 case Q3DEFORM_WAVE:
8123                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8124                                 break; // if wavefunc is a nop, ignore this transform
8125                         dynamicvertex = true;
8126                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8127                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8128                         break;
8129                 case Q3DEFORM_BULGE:
8130                         dynamicvertex = true;
8131                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8132                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8133                         break;
8134                 case Q3DEFORM_MOVE:
8135                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8136                                 break; // if wavefunc is a nop, ignore this transform
8137                         dynamicvertex = true;
8138                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8139                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8140                         break;
8141                 }
8142         }
8143         switch(rsurface.texture->tcgen.tcgen)
8144         {
8145         default:
8146         case Q3TCGEN_TEXTURE:
8147                 break;
8148         case Q3TCGEN_LIGHTMAP:
8149                 dynamicvertex = true;
8150                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8151                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8152                 break;
8153         case Q3TCGEN_VECTOR:
8154                 dynamicvertex = true;
8155                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8156                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8157                 break;
8158         case Q3TCGEN_ENVIRONMENT:
8159                 dynamicvertex = true;
8160                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8161                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8162                 break;
8163         }
8164         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8165         {
8166                 dynamicvertex = true;
8167                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8168                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8169         }
8170
8171         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8172         {
8173                 dynamicvertex = true;
8174                 batchneed |= BATCHNEED_NOGAPS;
8175                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8176         }
8177
8178         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8179         {
8180                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8181                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8182                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8183                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8184                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8185                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8186                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8187         }
8188
8189         // when the model data has no vertex buffer (dynamic mesh), we need to
8190         // eliminate gaps
8191         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8192                 batchneed |= BATCHNEED_NOGAPS;
8193
8194         // if needsupdate, we have to do a dynamic vertex batch for sure
8195         if (needsupdate & batchneed)
8196                 dynamicvertex = true;
8197
8198         // see if we need to build vertexmesh from arrays
8199         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8200                 dynamicvertex = true;
8201
8202         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8203         // also some drivers strongly dislike firstvertex
8204         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8205                 dynamicvertex = true;
8206
8207         rsurface.batchvertex3f = rsurface.modelvertex3f;
8208         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8209         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8210         rsurface.batchsvector3f = rsurface.modelsvector3f;
8211         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8212         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8213         rsurface.batchtvector3f = rsurface.modeltvector3f;
8214         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8215         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8216         rsurface.batchnormal3f = rsurface.modelnormal3f;
8217         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8218         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8219         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8220         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8221         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8222         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8223         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8224         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8225         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8226         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8227         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8228         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8229         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8230         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8231         rsurface.batchelement3i = rsurface.modelelement3i;
8232         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8233         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8234         rsurface.batchelement3s = rsurface.modelelement3s;
8235         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8236         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8237
8238         // if any dynamic vertex processing has to occur in software, we copy the
8239         // entire surface list together before processing to rebase the vertices
8240         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8241         //
8242         // if any gaps exist and we do not have a static vertex buffer, we have to
8243         // copy the surface list together to avoid wasting upload bandwidth on the
8244         // vertices in the gaps.
8245         //
8246         // if gaps exist and we have a static vertex buffer, we still have to
8247         // combine the index buffer ranges into one dynamic index buffer.
8248         //
8249         // in all cases we end up with data that can be drawn in one call.
8250
8251         if (!dynamicvertex)
8252         {
8253                 // static vertex data, just set pointers...
8254                 rsurface.batchgeneratedvertex = false;
8255                 // if there are gaps, we want to build a combined index buffer,
8256                 // otherwise use the original static buffer with an appropriate offset
8257                 if (gaps)
8258                 {
8259                         // build a new triangle elements array for this batch
8260                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8261                         rsurface.batchfirsttriangle = 0;
8262                         numtriangles = 0;
8263                         for (i = 0;i < texturenumsurfaces;i++)
8264                         {
8265                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8266                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8267                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8268                                 numtriangles += surfacenumtriangles;
8269                         }
8270                         rsurface.batchelement3i_indexbuffer = NULL;
8271                         rsurface.batchelement3i_bufferoffset = 0;
8272                         rsurface.batchelement3s = NULL;
8273                         rsurface.batchelement3s_indexbuffer = NULL;
8274                         rsurface.batchelement3s_bufferoffset = 0;
8275                         if (endvertex <= 65536)
8276                         {
8277                                 // make a 16bit (unsigned short) index array if possible
8278                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8279                                 for (i = 0;i < numtriangles*3;i++)
8280                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8281                         }
8282                 }
8283                 return;
8284         }
8285
8286         // something needs software processing, do it for real...
8287         // we only directly handle separate array data in this case and then
8288         // generate interleaved data if needed...
8289         rsurface.batchgeneratedvertex = true;
8290
8291         // now copy the vertex data into a combined array and make an index array
8292         // (this is what Quake3 does all the time)
8293         //if (gaps || rsurface.batchfirstvertex)
8294         {
8295                 rsurface.batchvertex3fbuffer = NULL;
8296                 rsurface.batchvertexmesh = NULL;
8297                 rsurface.batchvertexmeshbuffer = NULL;
8298                 rsurface.batchvertex3f = NULL;
8299                 rsurface.batchvertex3f_vertexbuffer = NULL;
8300                 rsurface.batchvertex3f_bufferoffset = 0;
8301                 rsurface.batchsvector3f = NULL;
8302                 rsurface.batchsvector3f_vertexbuffer = NULL;
8303                 rsurface.batchsvector3f_bufferoffset = 0;
8304                 rsurface.batchtvector3f = NULL;
8305                 rsurface.batchtvector3f_vertexbuffer = NULL;
8306                 rsurface.batchtvector3f_bufferoffset = 0;
8307                 rsurface.batchnormal3f = NULL;
8308                 rsurface.batchnormal3f_vertexbuffer = NULL;
8309                 rsurface.batchnormal3f_bufferoffset = 0;
8310                 rsurface.batchlightmapcolor4f = NULL;
8311                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8312                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8313                 rsurface.batchtexcoordtexture2f = NULL;
8314                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8315                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8316                 rsurface.batchtexcoordlightmap2f = NULL;
8317                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8318                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8319                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8320                 rsurface.batchelement3i_indexbuffer = NULL;
8321                 rsurface.batchelement3i_bufferoffset = 0;
8322                 rsurface.batchelement3s = NULL;
8323                 rsurface.batchelement3s_indexbuffer = NULL;
8324                 rsurface.batchelement3s_bufferoffset = 0;
8325                 // we'll only be setting up certain arrays as needed
8326                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8327                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8328                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8329                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8330                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8331                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8332                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8333                 {
8334                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8335                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8336                 }
8337                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8338                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8339                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8340                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8341                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8342                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8343                 numvertices = 0;
8344                 numtriangles = 0;
8345                 for (i = 0;i < texturenumsurfaces;i++)
8346                 {
8347                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8348                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8349                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8350                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8351                         // copy only the data requested
8352                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8353                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8354                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8355                         {
8356                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8357                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8358                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8359                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8360                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8361                                 {
8362                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8363                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8364                                 }
8365                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8366                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8367                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8368                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8369                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8370                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8371                         }
8372                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8373                         numvertices += surfacenumvertices;
8374                         numtriangles += surfacenumtriangles;
8375                 }
8376
8377                 // generate a 16bit index array as well if possible
8378                 // (in general, dynamic batches fit)
8379                 if (numvertices <= 65536)
8380                 {
8381                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8382                         for (i = 0;i < numtriangles*3;i++)
8383                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8384                 }
8385
8386                 // since we've copied everything, the batch now starts at 0
8387                 rsurface.batchfirstvertex = 0;
8388                 rsurface.batchnumvertices = batchnumvertices;
8389                 rsurface.batchfirsttriangle = 0;
8390                 rsurface.batchnumtriangles = batchnumtriangles;
8391         }
8392
8393         // q1bsp surfaces rendered in vertex color mode have to have colors
8394         // calculated based on lightstyles
8395         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8396         {
8397                 // generate color arrays for the surfaces in this list
8398                 int c[4];
8399                 int scale;
8400                 int size3;
8401                 const int *offsets;
8402                 const unsigned char *lm;
8403                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8404                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8405                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8406                 numvertices = 0;
8407                 for (i = 0;i < texturenumsurfaces;i++)
8408                 {
8409                         surface = texturesurfacelist[i];
8410                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8411                         surfacenumvertices = surface->num_vertices;
8412                         if (surface->lightmapinfo->samples)
8413                         {
8414                                 for (j = 0;j < surfacenumvertices;j++)
8415                                 {
8416                                         lm = surface->lightmapinfo->samples + offsets[j];
8417                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8418                                         VectorScale(lm, scale, c);
8419                                         if (surface->lightmapinfo->styles[1] != 255)
8420                                         {
8421                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8422                                                 lm += size3;
8423                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8424                                                 VectorMA(c, scale, lm, c);
8425                                                 if (surface->lightmapinfo->styles[2] != 255)
8426                                                 {
8427                                                         lm += size3;
8428                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8429                                                         VectorMA(c, scale, lm, c);
8430                                                         if (surface->lightmapinfo->styles[3] != 255)
8431                                                         {
8432                                                                 lm += size3;
8433                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8434                                                                 VectorMA(c, scale, lm, c);
8435                                                         }
8436                                                 }
8437                                         }
8438                                         c[0] >>= 7;
8439                                         c[1] >>= 7;
8440                                         c[2] >>= 7;
8441                                         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);
8442                                         numvertices++;
8443                                 }
8444                         }
8445                         else
8446                         {
8447                                 for (j = 0;j < surfacenumvertices;j++)
8448                                 {
8449                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8450                                         numvertices++;
8451                                 }
8452                         }
8453                 }
8454         }
8455
8456         // if vertices are deformed (sprite flares and things in maps, possibly
8457         // water waves, bulges and other deformations), modify the copied vertices
8458         // in place
8459         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8460         {
8461                 switch (deform->deform)
8462                 {
8463                 default:
8464                 case Q3DEFORM_PROJECTIONSHADOW:
8465                 case Q3DEFORM_TEXT0:
8466                 case Q3DEFORM_TEXT1:
8467                 case Q3DEFORM_TEXT2:
8468                 case Q3DEFORM_TEXT3:
8469                 case Q3DEFORM_TEXT4:
8470                 case Q3DEFORM_TEXT5:
8471                 case Q3DEFORM_TEXT6:
8472                 case Q3DEFORM_TEXT7:
8473                 case Q3DEFORM_NONE:
8474                         break;
8475                 case Q3DEFORM_AUTOSPRITE:
8476                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8477                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8478                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8479                         VectorNormalize(newforward);
8480                         VectorNormalize(newright);
8481                         VectorNormalize(newup);
8482 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8483 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8484 //                      rsurface.batchvertex3f_bufferoffset = 0;
8485 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8486 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8487 //                      rsurface.batchsvector3f_bufferoffset = 0;
8488 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8489 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8490 //                      rsurface.batchtvector3f_bufferoffset = 0;
8491 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8492 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8493 //                      rsurface.batchnormal3f_bufferoffset = 0;
8494                         // a single autosprite surface can contain multiple sprites...
8495                         for (j = 0;j < batchnumvertices - 3;j += 4)
8496                         {
8497                                 VectorClear(center);
8498                                 for (i = 0;i < 4;i++)
8499                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8500                                 VectorScale(center, 0.25f, center);
8501                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8502                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8503                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8504                                 for (i = 0;i < 4;i++)
8505                                 {
8506                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8507                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8508                                 }
8509                         }
8510                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8511                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8512                         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);
8513                         break;
8514                 case Q3DEFORM_AUTOSPRITE2:
8515                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8516                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8517                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8518                         VectorNormalize(newforward);
8519                         VectorNormalize(newright);
8520                         VectorNormalize(newup);
8521 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8522 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8523 //                      rsurface.batchvertex3f_bufferoffset = 0;
8524                         {
8525                                 const float *v1, *v2;
8526                                 vec3_t start, end;
8527                                 float f, l;
8528                                 struct
8529                                 {
8530                                         float length2;
8531                                         const float *v1;
8532                                         const float *v2;
8533                                 }
8534                                 shortest[2];
8535                                 memset(shortest, 0, sizeof(shortest));
8536                                 // a single autosprite surface can contain multiple sprites...
8537                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8538                                 {
8539                                         VectorClear(center);
8540                                         for (i = 0;i < 4;i++)
8541                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8542                                         VectorScale(center, 0.25f, center);
8543                                         // find the two shortest edges, then use them to define the
8544                                         // axis vectors for rotating around the central axis
8545                                         for (i = 0;i < 6;i++)
8546                                         {
8547                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8548                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8549                                                 l = VectorDistance2(v1, v2);
8550                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8551                                                 if (v1[2] != v2[2])
8552                                                         l += (1.0f / 1024.0f);
8553                                                 if (shortest[0].length2 > l || i == 0)
8554                                                 {
8555                                                         shortest[1] = shortest[0];
8556                                                         shortest[0].length2 = l;
8557                                                         shortest[0].v1 = v1;
8558                                                         shortest[0].v2 = v2;
8559                                                 }
8560                                                 else if (shortest[1].length2 > l || i == 1)
8561                                                 {
8562                                                         shortest[1].length2 = l;
8563                                                         shortest[1].v1 = v1;
8564                                                         shortest[1].v2 = v2;
8565                                                 }
8566                                         }
8567                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8568                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8569                                         // this calculates the right vector from the shortest edge
8570                                         // and the up vector from the edge midpoints
8571                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8572                                         VectorNormalize(right);
8573                                         VectorSubtract(end, start, up);
8574                                         VectorNormalize(up);
8575                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8576                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8577                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8578                                         VectorNegate(forward, forward);
8579                                         VectorReflect(forward, 0, up, forward);
8580                                         VectorNormalize(forward);
8581                                         CrossProduct(up, forward, newright);
8582                                         VectorNormalize(newright);
8583                                         // rotate the quad around the up axis vector, this is made
8584                                         // especially easy by the fact we know the quad is flat,
8585                                         // so we only have to subtract the center position and
8586                                         // measure distance along the right vector, and then
8587                                         // multiply that by the newright vector and add back the
8588                                         // center position
8589                                         // we also need to subtract the old position to undo the
8590                                         // displacement from the center, which we do with a
8591                                         // DotProduct, the subtraction/addition of center is also
8592                                         // optimized into DotProducts here
8593                                         l = DotProduct(right, center);
8594                                         for (i = 0;i < 4;i++)
8595                                         {
8596                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8597                                                 f = DotProduct(right, v1) - l;
8598                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8599                                         }
8600                                 }
8601                         }
8602                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8603                         {
8604 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8605 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8606 //                              rsurface.batchnormal3f_bufferoffset = 0;
8607                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8608                         }
8609                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8610                         {
8611 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8612 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8613 //                              rsurface.batchsvector3f_bufferoffset = 0;
8614 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8615 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8616 //                              rsurface.batchtvector3f_bufferoffset = 0;
8617                                 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);
8618                         }
8619                         break;
8620                 case Q3DEFORM_NORMAL:
8621                         // deform the normals to make reflections wavey
8622                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8623                         rsurface.batchnormal3f_vertexbuffer = NULL;
8624                         rsurface.batchnormal3f_bufferoffset = 0;
8625                         for (j = 0;j < batchnumvertices;j++)
8626                         {
8627                                 float vertex[3];
8628                                 float *normal = rsurface.batchnormal3f + 3*j;
8629                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8630                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8631                                 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]);
8632                                 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]);
8633                                 VectorNormalize(normal);
8634                         }
8635                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8636                         {
8637 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8638 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8639 //                              rsurface.batchsvector3f_bufferoffset = 0;
8640 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8641 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8642 //                              rsurface.batchtvector3f_bufferoffset = 0;
8643                                 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);
8644                         }
8645                         break;
8646                 case Q3DEFORM_WAVE:
8647                         // deform vertex array to make wavey water and flags and such
8648                         waveparms[0] = deform->waveparms[0];
8649                         waveparms[1] = deform->waveparms[1];
8650                         waveparms[2] = deform->waveparms[2];
8651                         waveparms[3] = deform->waveparms[3];
8652                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8653                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8654                         // this is how a divisor of vertex influence on deformation
8655                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8656                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8657 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8658 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8659 //                      rsurface.batchvertex3f_bufferoffset = 0;
8660 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8661 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8662 //                      rsurface.batchnormal3f_bufferoffset = 0;
8663                         for (j = 0;j < batchnumvertices;j++)
8664                         {
8665                                 // if the wavefunc depends on time, evaluate it per-vertex
8666                                 if (waveparms[3])
8667                                 {
8668                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8669                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8670                                 }
8671                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8672                         }
8673                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8674                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8675                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8676                         {
8677 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8678 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8679 //                              rsurface.batchsvector3f_bufferoffset = 0;
8680 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8681 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8682 //                              rsurface.batchtvector3f_bufferoffset = 0;
8683                                 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);
8684                         }
8685                         break;
8686                 case Q3DEFORM_BULGE:
8687                         // deform vertex array to make the surface have moving bulges
8688 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8689 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8690 //                      rsurface.batchvertex3f_bufferoffset = 0;
8691 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8692 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8693 //                      rsurface.batchnormal3f_bufferoffset = 0;
8694                         for (j = 0;j < batchnumvertices;j++)
8695                         {
8696                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8697                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8698                         }
8699                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8700                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8701                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8702                         {
8703 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8704 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8705 //                              rsurface.batchsvector3f_bufferoffset = 0;
8706 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8707 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8708 //                              rsurface.batchtvector3f_bufferoffset = 0;
8709                                 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);
8710                         }
8711                         break;
8712                 case Q3DEFORM_MOVE:
8713                         // deform vertex array
8714                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8715                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8716                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8717                         VectorScale(deform->parms, scale, waveparms);
8718 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8719 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8720 //                      rsurface.batchvertex3f_bufferoffset = 0;
8721                         for (j = 0;j < batchnumvertices;j++)
8722                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8723                         break;
8724                 }
8725         }
8726
8727         // generate texcoords based on the chosen texcoord source
8728         switch(rsurface.texture->tcgen.tcgen)
8729         {
8730         default:
8731         case Q3TCGEN_TEXTURE:
8732                 break;
8733         case Q3TCGEN_LIGHTMAP:
8734 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8735 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8736 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8737                 if (rsurface.batchtexcoordlightmap2f)
8738                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8739                 break;
8740         case Q3TCGEN_VECTOR:
8741 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8742 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8743 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8744                 for (j = 0;j < batchnumvertices;j++)
8745                 {
8746                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8747                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8748                 }
8749                 break;
8750         case Q3TCGEN_ENVIRONMENT:
8751                 // make environment reflections using a spheremap
8752                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8753                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8754                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8755                 for (j = 0;j < batchnumvertices;j++)
8756                 {
8757                         // identical to Q3A's method, but executed in worldspace so
8758                         // carried models can be shiny too
8759
8760                         float viewer[3], d, reflected[3], worldreflected[3];
8761
8762                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8763                         // VectorNormalize(viewer);
8764
8765                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8766
8767                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8768                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8769                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8770                         // note: this is proportinal to viewer, so we can normalize later
8771
8772                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8773                         VectorNormalize(worldreflected);
8774
8775                         // note: this sphere map only uses world x and z!
8776                         // so positive and negative y will LOOK THE SAME.
8777                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8778                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8779                 }
8780                 break;
8781         }
8782         // the only tcmod that needs software vertex processing is turbulent, so
8783         // check for it here and apply the changes if needed
8784         // and we only support that as the first one
8785         // (handling a mixture of turbulent and other tcmods would be problematic
8786         //  without punting it entirely to a software path)
8787         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8788         {
8789                 amplitude = rsurface.texture->tcmods[0].parms[1];
8790                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8791 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8792 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8793 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8794                 for (j = 0;j < batchnumvertices;j++)
8795                 {
8796                         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);
8797                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8798                 }
8799         }
8800
8801         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8802         {
8803                 // convert the modified arrays to vertex structs
8804 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8805 //              rsurface.batchvertexmeshbuffer = NULL;
8806                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8807                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8808                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8809                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8810                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8811                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8812                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8813                 {
8814                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8815                         {
8816                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8817                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8818                         }
8819                 }
8820                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8821                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8822                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8823                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8824                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8825                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8826                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8827                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8828                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8829         }
8830 }
8831
8832 void RSurf_DrawBatch(void)
8833 {
8834         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8835         // through the pipeline, killing it earlier in the pipeline would have
8836         // per-surface overhead rather than per-batch overhead, so it's best to
8837         // reject it here, before it hits glDraw.
8838         if (rsurface.batchnumtriangles == 0)
8839                 return;
8840 #if 0
8841         // batch debugging code
8842         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8843         {
8844                 int i;
8845                 int j;
8846                 int c;
8847                 const int *e;
8848                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8849                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8850                 {
8851                         c = e[i];
8852                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8853                         {
8854                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8855                                 {
8856                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8857                                                 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);
8858                                         break;
8859                                 }
8860                         }
8861                 }
8862         }
8863 #endif
8864         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);
8865 }
8866
8867 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8868 {
8869         // pick the closest matching water plane
8870         int planeindex, vertexindex, bestplaneindex = -1;
8871         float d, bestd;
8872         vec3_t vert;
8873         const float *v;
8874         r_waterstate_waterplane_t *p;
8875         qboolean prepared = false;
8876         bestd = 0;
8877         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8878         {
8879                 if(p->camera_entity != rsurface.texture->camera_entity)
8880                         continue;
8881                 d = 0;
8882                 if(!prepared)
8883                 {
8884                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8885                         prepared = true;
8886                         if(rsurface.batchnumvertices == 0)
8887                                 break;
8888                 }
8889                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8890                 {
8891                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8892                         d += fabs(PlaneDiff(vert, &p->plane));
8893                 }
8894                 if (bestd > d || bestplaneindex < 0)
8895                 {
8896                         bestd = d;
8897                         bestplaneindex = planeindex;
8898                 }
8899         }
8900         return bestplaneindex;
8901         // NOTE: this MAY return a totally unrelated water plane; we can ignore
8902         // this situation though, as it might be better to render single larger
8903         // batches with useless stuff (backface culled for example) than to
8904         // render multiple smaller batches
8905 }
8906
8907 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8908 {
8909         int i;
8910         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8911         rsurface.passcolor4f_vertexbuffer = 0;
8912         rsurface.passcolor4f_bufferoffset = 0;
8913         for (i = 0;i < rsurface.batchnumvertices;i++)
8914                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8915 }
8916
8917 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8918 {
8919         int i;
8920         float f;
8921         const float *v;
8922         const float *c;
8923         float *c2;
8924         if (rsurface.passcolor4f)
8925         {
8926                 // generate color arrays
8927                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
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, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
8932                 {
8933                         f = RSurf_FogVertex(v);
8934                         c2[0] = c[0] * f;
8935                         c2[1] = c[1] * f;
8936                         c2[2] = c[2] * f;
8937                         c2[3] = c[3];
8938                 }
8939         }
8940         else
8941         {
8942                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8943                 rsurface.passcolor4f_vertexbuffer = 0;
8944                 rsurface.passcolor4f_bufferoffset = 0;
8945                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8946                 {
8947                         f = RSurf_FogVertex(v);
8948                         c2[0] = f;
8949                         c2[1] = f;
8950                         c2[2] = f;
8951                         c2[3] = 1;
8952                 }
8953         }
8954 }
8955
8956 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8957 {
8958         int i;
8959         float f;
8960         const float *v;
8961         const float *c;
8962         float *c2;
8963         if (!rsurface.passcolor4f)
8964                 return;
8965         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8966         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8967         rsurface.passcolor4f_vertexbuffer = 0;
8968         rsurface.passcolor4f_bufferoffset = 0;
8969         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)
8970         {
8971                 f = RSurf_FogVertex(v);
8972                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8973                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8974                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8975                 c2[3] = c[3];
8976         }
8977 }
8978
8979 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
8980 {
8981         int i;
8982         const float *c;
8983         float *c2;
8984         if (!rsurface.passcolor4f)
8985                 return;
8986         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8987         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8988         rsurface.passcolor4f_vertexbuffer = 0;
8989         rsurface.passcolor4f_bufferoffset = 0;
8990         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
8991         {
8992                 c2[0] = c[0] * r;
8993                 c2[1] = c[1] * g;
8994                 c2[2] = c[2] * b;
8995                 c2[3] = c[3] * a;
8996         }
8997 }
8998
8999 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9000 {
9001         int i;
9002         const float *c;
9003         float *c2;
9004         if (!rsurface.passcolor4f)
9005                 return;
9006         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9007         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9008         rsurface.passcolor4f_vertexbuffer = 0;
9009         rsurface.passcolor4f_bufferoffset = 0;
9010         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9011         {
9012                 c2[0] = c[0] + r_refdef.scene.ambient;
9013                 c2[1] = c[1] + r_refdef.scene.ambient;
9014                 c2[2] = c[2] + r_refdef.scene.ambient;
9015                 c2[3] = c[3];
9016         }
9017 }
9018
9019 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9020 {
9021         // TODO: optimize
9022         rsurface.passcolor4f = NULL;
9023         rsurface.passcolor4f_vertexbuffer = 0;
9024         rsurface.passcolor4f_bufferoffset = 0;
9025         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9026         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9027         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9028         GL_Color(r, g, b, a);
9029         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9030         RSurf_DrawBatch();
9031 }
9032
9033 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9034 {
9035         // TODO: optimize applyfog && applycolor case
9036         // just apply fog if necessary, and tint the fog color array if necessary
9037         rsurface.passcolor4f = NULL;
9038         rsurface.passcolor4f_vertexbuffer = 0;
9039         rsurface.passcolor4f_bufferoffset = 0;
9040         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9041         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9042         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9043         GL_Color(r, g, b, a);
9044         RSurf_DrawBatch();
9045 }
9046
9047 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9048 {
9049         // TODO: optimize
9050         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9051         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9052         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9053         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9054         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9055         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9056         GL_Color(r, g, b, a);
9057         RSurf_DrawBatch();
9058 }
9059
9060 static void RSurf_DrawBatch_GL11_ClampColor(void)
9061 {
9062         int i;
9063         const float *c1;
9064         float *c2;
9065         if (!rsurface.passcolor4f)
9066                 return;
9067         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9068         {
9069                 c2[0] = bound(0.0f, c1[0], 1.0f);
9070                 c2[1] = bound(0.0f, c1[1], 1.0f);
9071                 c2[2] = bound(0.0f, c1[2], 1.0f);
9072                 c2[3] = bound(0.0f, c1[3], 1.0f);
9073         }
9074 }
9075
9076 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9077 {
9078         int i;
9079         float f;
9080         const float *v;
9081         const float *n;
9082         float *c;
9083         //vec3_t eyedir;
9084
9085         // fake shading
9086         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9087         rsurface.passcolor4f_vertexbuffer = 0;
9088         rsurface.passcolor4f_bufferoffset = 0;
9089         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)
9090         {
9091                 f = -DotProduct(r_refdef.view.forward, n);
9092                 f = max(0, f);
9093                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9094                 f *= r_refdef.lightmapintensity;
9095                 Vector4Set(c, f, f, f, 1);
9096         }
9097 }
9098
9099 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9100 {
9101         RSurf_DrawBatch_GL11_ApplyFakeLight();
9102         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9103         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9104         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9105         GL_Color(r, g, b, a);
9106         RSurf_DrawBatch();
9107 }
9108
9109 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9110 {
9111         int i;
9112         float f;
9113         float alpha;
9114         const float *v;
9115         const float *n;
9116         float *c;
9117         vec3_t ambientcolor;
9118         vec3_t diffusecolor;
9119         vec3_t lightdir;
9120         // TODO: optimize
9121         // model lighting
9122         VectorCopy(rsurface.modellight_lightdir, lightdir);
9123         f = 0.5f * r_refdef.lightmapintensity;
9124         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9125         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9126         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9127         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9128         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9129         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9130         alpha = *a;
9131         if (VectorLength2(diffusecolor) > 0)
9132         {
9133                 // q3-style directional shading
9134                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9135                 rsurface.passcolor4f_vertexbuffer = 0;
9136                 rsurface.passcolor4f_bufferoffset = 0;
9137                 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)
9138                 {
9139                         if ((f = DotProduct(n, lightdir)) > 0)
9140                                 VectorMA(ambientcolor, f, diffusecolor, c);
9141                         else
9142                                 VectorCopy(ambientcolor, c);
9143                         c[3] = alpha;
9144                 }
9145                 *r = 1;
9146                 *g = 1;
9147                 *b = 1;
9148                 *a = 1;
9149                 *applycolor = false;
9150         }
9151         else
9152         {
9153                 *r = ambientcolor[0];
9154                 *g = ambientcolor[1];
9155                 *b = ambientcolor[2];
9156                 rsurface.passcolor4f = NULL;
9157                 rsurface.passcolor4f_vertexbuffer = 0;
9158                 rsurface.passcolor4f_bufferoffset = 0;
9159         }
9160 }
9161
9162 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9163 {
9164         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9165         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9166         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9167         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9168         GL_Color(r, g, b, a);
9169         RSurf_DrawBatch();
9170 }
9171
9172 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9173 {
9174         int i;
9175         float f;
9176         const float *v;
9177         float *c;
9178         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9179         {
9180                 f = 1 - RSurf_FogVertex(v);
9181                 c[0] = r;
9182                 c[1] = g;
9183                 c[2] = b;
9184                 c[3] = f * a;
9185         }
9186 }
9187
9188 void RSurf_SetupDepthAndCulling(void)
9189 {
9190         // submodels are biased to avoid z-fighting with world surfaces that they
9191         // may be exactly overlapping (avoids z-fighting artifacts on certain
9192         // doors and things in Quake maps)
9193         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9194         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9195         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9196         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9197 }
9198
9199 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9200 {
9201         // transparent sky would be ridiculous
9202         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9203                 return;
9204         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9205         skyrenderlater = true;
9206         RSurf_SetupDepthAndCulling();
9207         GL_DepthMask(true);
9208         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9209         // skymasking on them, and Quake3 never did sky masking (unlike
9210         // software Quake and software Quake2), so disable the sky masking
9211         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9212         // and skymasking also looks very bad when noclipping outside the
9213         // level, so don't use it then either.
9214         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9215         {
9216                 R_Mesh_ResetTextureState();
9217                 if (skyrendermasked)
9218                 {
9219                         R_SetupShader_DepthOrShadow();
9220                         // depth-only (masking)
9221                         GL_ColorMask(0,0,0,0);
9222                         // just to make sure that braindead drivers don't draw
9223                         // anything despite that colormask...
9224                         GL_BlendFunc(GL_ZERO, GL_ONE);
9225                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9226                         if (rsurface.batchvertex3fbuffer)
9227                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9228                         else
9229                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9230                 }
9231                 else
9232                 {
9233                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9234                         // fog sky
9235                         GL_BlendFunc(GL_ONE, GL_ZERO);
9236                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9237                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9238                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9239                 }
9240                 RSurf_DrawBatch();
9241                 if (skyrendermasked)
9242                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9243         }
9244         R_Mesh_ResetTextureState();
9245         GL_Color(1, 1, 1, 1);
9246 }
9247
9248 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9249 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9250 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9251 {
9252         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9253                 return;
9254         if (prepass)
9255         {
9256                 // render screenspace normalmap to texture
9257                 GL_DepthMask(true);
9258                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9259                 RSurf_DrawBatch();
9260                 return;
9261         }
9262
9263         // bind lightmap texture
9264
9265         // water/refraction/reflection/camera surfaces have to be handled specially
9266         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9267         {
9268                 int start, end, startplaneindex;
9269                 for (start = 0;start < texturenumsurfaces;start = end)
9270                 {
9271                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9272                         if(startplaneindex < 0)
9273                         {
9274                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9275                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9276                                 end = start + 1;
9277                                 continue;
9278                         }
9279                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9280                                 ;
9281                         // now that we have a batch using the same planeindex, render it
9282                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9283                         {
9284                                 // render water or distortion background
9285                                 GL_DepthMask(true);
9286                                 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));
9287                                 RSurf_DrawBatch();
9288                                 // blend surface on top
9289                                 GL_DepthMask(false);
9290                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9291                                 RSurf_DrawBatch();
9292                         }
9293                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9294                         {
9295                                 // render surface with reflection texture as input
9296                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9297                                 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));
9298                                 RSurf_DrawBatch();
9299                         }
9300                 }
9301                 return;
9302         }
9303
9304         // render surface batch normally
9305         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9306         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9307         RSurf_DrawBatch();
9308 }
9309
9310 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9311 {
9312         // OpenGL 1.3 path - anything not completely ancient
9313         qboolean applycolor;
9314         qboolean applyfog;
9315         int layerindex;
9316         const texturelayer_t *layer;
9317         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);
9318         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9319
9320         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9321         {
9322                 vec4_t layercolor;
9323                 int layertexrgbscale;
9324                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9325                 {
9326                         if (layerindex == 0)
9327                                 GL_AlphaTest(true);
9328                         else
9329                         {
9330                                 GL_AlphaTest(false);
9331                                 GL_DepthFunc(GL_EQUAL);
9332                         }
9333                 }
9334                 GL_DepthMask(layer->depthmask && writedepth);
9335                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9336                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9337                 {
9338                         layertexrgbscale = 4;
9339                         VectorScale(layer->color, 0.25f, layercolor);
9340                 }
9341                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9342                 {
9343                         layertexrgbscale = 2;
9344                         VectorScale(layer->color, 0.5f, layercolor);
9345                 }
9346                 else
9347                 {
9348                         layertexrgbscale = 1;
9349                         VectorScale(layer->color, 1.0f, layercolor);
9350                 }
9351                 layercolor[3] = layer->color[3];
9352                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9353                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9354                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9355                 switch (layer->type)
9356                 {
9357                 case TEXTURELAYERTYPE_LITTEXTURE:
9358                         // single-pass lightmapped texture with 2x rgbscale
9359                         R_Mesh_TexBind(0, r_texture_white);
9360                         R_Mesh_TexMatrix(0, NULL);
9361                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9362                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9363                         R_Mesh_TexBind(1, layer->texture);
9364                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9365                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9366                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9367                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9368                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9369                         else if (FAKELIGHT_ENABLED)
9370                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9371                         else if (rsurface.uselightmaptexture)
9372                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9373                         else
9374                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9375                         break;
9376                 case TEXTURELAYERTYPE_TEXTURE:
9377                         // singletexture unlit texture with transparency support
9378                         R_Mesh_TexBind(0, layer->texture);
9379                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9380                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9381                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9382                         R_Mesh_TexBind(1, 0);
9383                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9384                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9385                         break;
9386                 case TEXTURELAYERTYPE_FOG:
9387                         // singletexture fogging
9388                         if (layer->texture)
9389                         {
9390                                 R_Mesh_TexBind(0, layer->texture);
9391                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9392                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9393                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9394                         }
9395                         else
9396                         {
9397                                 R_Mesh_TexBind(0, 0);
9398                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9399                         }
9400                         R_Mesh_TexBind(1, 0);
9401                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9402                         // generate a color array for the fog pass
9403                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9404                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9405                         RSurf_DrawBatch();
9406                         break;
9407                 default:
9408                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9409                 }
9410         }
9411         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9412         {
9413                 GL_DepthFunc(GL_LEQUAL);
9414                 GL_AlphaTest(false);
9415         }
9416 }
9417
9418 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9419 {
9420         // OpenGL 1.1 - crusty old voodoo path
9421         qboolean applyfog;
9422         int layerindex;
9423         const texturelayer_t *layer;
9424         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);
9425         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9426
9427         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9428         {
9429                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9430                 {
9431                         if (layerindex == 0)
9432                                 GL_AlphaTest(true);
9433                         else
9434                         {
9435                                 GL_AlphaTest(false);
9436                                 GL_DepthFunc(GL_EQUAL);
9437                         }
9438                 }
9439                 GL_DepthMask(layer->depthmask && writedepth);
9440                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9441                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9442                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9443                 switch (layer->type)
9444                 {
9445                 case TEXTURELAYERTYPE_LITTEXTURE:
9446                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9447                         {
9448                                 // two-pass lit texture with 2x rgbscale
9449                                 // first the lightmap pass
9450                                 R_Mesh_TexBind(0, r_texture_white);
9451                                 R_Mesh_TexMatrix(0, NULL);
9452                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9453                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9454                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9455                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9456                                 else if (FAKELIGHT_ENABLED)
9457                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9458                                 else if (rsurface.uselightmaptexture)
9459                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9460                                 else
9461                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9462                                 // then apply the texture to it
9463                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9464                                 R_Mesh_TexBind(0, layer->texture);
9465                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9466                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9467                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9468                                 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);
9469                         }
9470                         else
9471                         {
9472                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9473                                 R_Mesh_TexBind(0, layer->texture);
9474                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9475                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9476                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9477                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9478                                         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);
9479                                 else
9480                                         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);
9481                         }
9482                         break;
9483                 case TEXTURELAYERTYPE_TEXTURE:
9484                         // singletexture unlit texture with transparency support
9485                         R_Mesh_TexBind(0, layer->texture);
9486                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9487                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9488                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9489                         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);
9490                         break;
9491                 case TEXTURELAYERTYPE_FOG:
9492                         // singletexture fogging
9493                         if (layer->texture)
9494                         {
9495                                 R_Mesh_TexBind(0, layer->texture);
9496                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9497                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9498                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9499                         }
9500                         else
9501                         {
9502                                 R_Mesh_TexBind(0, 0);
9503                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9504                         }
9505                         // generate a color array for the fog pass
9506                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9507                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9508                         RSurf_DrawBatch();
9509                         break;
9510                 default:
9511                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9512                 }
9513         }
9514         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9515         {
9516                 GL_DepthFunc(GL_LEQUAL);
9517                 GL_AlphaTest(false);
9518         }
9519 }
9520
9521 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9522 {
9523         int vi;
9524         int j;
9525         r_vertexgeneric_t *batchvertex;
9526         float c[4];
9527
9528 //      R_Mesh_ResetTextureState();
9529         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9530
9531         if(rsurface.texture && rsurface.texture->currentskinframe)
9532         {
9533                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9534                 c[3] *= rsurface.texture->currentalpha;
9535         }
9536         else
9537         {
9538                 c[0] = 1;
9539                 c[1] = 0;
9540                 c[2] = 1;
9541                 c[3] = 1;
9542         }
9543
9544         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9545         {
9546                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9547                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9548                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9549         }
9550
9551         // brighten it up (as texture value 127 means "unlit")
9552         c[0] *= 2 * r_refdef.view.colorscale;
9553         c[1] *= 2 * r_refdef.view.colorscale;
9554         c[2] *= 2 * r_refdef.view.colorscale;
9555
9556         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9557                 c[3] *= r_wateralpha.value;
9558
9559         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9560         {
9561                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9562                 GL_DepthMask(false);
9563         }
9564         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9565         {
9566                 GL_BlendFunc(GL_ONE, GL_ONE);
9567                 GL_DepthMask(false);
9568         }
9569         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9570         {
9571                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9572                 GL_DepthMask(false);
9573         }
9574         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9575         {
9576                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9577                 GL_DepthMask(false);
9578         }
9579         else
9580         {
9581                 GL_BlendFunc(GL_ONE, GL_ZERO);
9582                 GL_DepthMask(writedepth);
9583         }
9584
9585         if (r_showsurfaces.integer == 3)
9586         {
9587                 rsurface.passcolor4f = NULL;
9588
9589                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9590                 {
9591                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9592
9593                         rsurface.passcolor4f = NULL;
9594                         rsurface.passcolor4f_vertexbuffer = 0;
9595                         rsurface.passcolor4f_bufferoffset = 0;
9596                 }
9597                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9598                 {
9599                         qboolean applycolor = true;
9600                         float one = 1.0;
9601
9602                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9603
9604                         r_refdef.lightmapintensity = 1;
9605                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9606                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9607                 }
9608                 else if (FAKELIGHT_ENABLED)
9609                 {
9610                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9611
9612                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9613                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9614                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9615                 }
9616                 else
9617                 {
9618                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9619
9620                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9621                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9622                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9623                 }
9624
9625                 if(!rsurface.passcolor4f)
9626                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9627
9628                 RSurf_DrawBatch_GL11_ApplyAmbient();
9629                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9630                 if(r_refdef.fogenabled)
9631                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9632                 RSurf_DrawBatch_GL11_ClampColor();
9633
9634                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9635                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9636                 RSurf_DrawBatch();
9637         }
9638         else if (!r_refdef.view.showdebug)
9639         {
9640                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9641                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9642                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9643                 {
9644                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9645                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9646                 }
9647                 R_Mesh_PrepareVertices_Generic_Unlock();
9648                 RSurf_DrawBatch();
9649         }
9650         else if (r_showsurfaces.integer == 4)
9651         {
9652                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9653                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9654                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9655                 {
9656                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9657                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9658                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9659                 }
9660                 R_Mesh_PrepareVertices_Generic_Unlock();
9661                 RSurf_DrawBatch();
9662         }
9663         else if (r_showsurfaces.integer == 2)
9664         {
9665                 const int *e;
9666                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9667                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9668                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9669                 {
9670                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9671                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9672                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9673                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9674                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9675                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9676                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9677                 }
9678                 R_Mesh_PrepareVertices_Generic_Unlock();
9679                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9680         }
9681         else
9682         {
9683                 int texturesurfaceindex;
9684                 int k;
9685                 const msurface_t *surface;
9686                 float surfacecolor4f[4];
9687                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9688                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9689                 vi = 0;
9690                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9691                 {
9692                         surface = texturesurfacelist[texturesurfaceindex];
9693                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9694                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9695                         for (j = 0;j < surface->num_vertices;j++)
9696                         {
9697                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9698                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9699                                 vi++;
9700                         }
9701                 }
9702                 R_Mesh_PrepareVertices_Generic_Unlock();
9703                 RSurf_DrawBatch();
9704         }
9705 }
9706
9707 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9708 {
9709         CHECKGLERROR
9710         RSurf_SetupDepthAndCulling();
9711         if (r_showsurfaces.integer)
9712         {
9713                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9714                 return;
9715         }
9716         switch (vid.renderpath)
9717         {
9718         case RENDERPATH_GL20:
9719         case RENDERPATH_D3D9:
9720         case RENDERPATH_D3D10:
9721         case RENDERPATH_D3D11:
9722         case RENDERPATH_SOFT:
9723         case RENDERPATH_GLES2:
9724                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9725                 break;
9726         case RENDERPATH_GL13:
9727                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9728                 break;
9729         case RENDERPATH_GL11:
9730                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9731                 break;
9732         }
9733         CHECKGLERROR
9734 }
9735
9736 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9737 {
9738         CHECKGLERROR
9739         RSurf_SetupDepthAndCulling();
9740         if (r_showsurfaces.integer)
9741         {
9742                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9743                 return;
9744         }
9745         switch (vid.renderpath)
9746         {
9747         case RENDERPATH_GL20:
9748         case RENDERPATH_D3D9:
9749         case RENDERPATH_D3D10:
9750         case RENDERPATH_D3D11:
9751         case RENDERPATH_SOFT:
9752         case RENDERPATH_GLES2:
9753                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9754                 break;
9755         case RENDERPATH_GL13:
9756                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9757                 break;
9758         case RENDERPATH_GL11:
9759                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9760                 break;
9761         }
9762         CHECKGLERROR
9763 }
9764
9765 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9766 {
9767         int i, j;
9768         int texturenumsurfaces, endsurface;
9769         texture_t *texture;
9770         const msurface_t *surface;
9771 #define MAXBATCH_TRANSPARENTSURFACES 256
9772         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9773
9774         // if the model is static it doesn't matter what value we give for
9775         // wantnormals and wanttangents, so this logic uses only rules applicable
9776         // to a model, knowing that they are meaningless otherwise
9777         if (ent == r_refdef.scene.worldentity)
9778                 RSurf_ActiveWorldEntity();
9779         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9780                 RSurf_ActiveModelEntity(ent, false, false, false);
9781         else
9782         {
9783                 switch (vid.renderpath)
9784                 {
9785                 case RENDERPATH_GL20:
9786                 case RENDERPATH_D3D9:
9787                 case RENDERPATH_D3D10:
9788                 case RENDERPATH_D3D11:
9789                 case RENDERPATH_SOFT:
9790                 case RENDERPATH_GLES2:
9791                         RSurf_ActiveModelEntity(ent, true, true, false);
9792                         break;
9793                 case RENDERPATH_GL13:
9794                 case RENDERPATH_GL11:
9795                         RSurf_ActiveModelEntity(ent, true, false, false);
9796                         break;
9797                 }
9798         }
9799
9800         if (r_transparentdepthmasking.integer)
9801         {
9802                 qboolean setup = false;
9803                 for (i = 0;i < numsurfaces;i = j)
9804                 {
9805                         j = i + 1;
9806                         surface = rsurface.modelsurfaces + surfacelist[i];
9807                         texture = surface->texture;
9808                         rsurface.texture = R_GetCurrentTexture(texture);
9809                         rsurface.lightmaptexture = NULL;
9810                         rsurface.deluxemaptexture = NULL;
9811                         rsurface.uselightmaptexture = false;
9812                         // scan ahead until we find a different texture
9813                         endsurface = min(i + 1024, numsurfaces);
9814                         texturenumsurfaces = 0;
9815                         texturesurfacelist[texturenumsurfaces++] = surface;
9816                         for (;j < endsurface;j++)
9817                         {
9818                                 surface = rsurface.modelsurfaces + surfacelist[j];
9819                                 if (texture != surface->texture)
9820                                         break;
9821                                 texturesurfacelist[texturenumsurfaces++] = surface;
9822                         }
9823                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9824                                 continue;
9825                         // render the range of surfaces as depth
9826                         if (!setup)
9827                         {
9828                                 setup = true;
9829                                 GL_ColorMask(0,0,0,0);
9830                                 GL_Color(1,1,1,1);
9831                                 GL_DepthTest(true);
9832                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9833                                 GL_DepthMask(true);
9834 //                              R_Mesh_ResetTextureState();
9835                                 R_SetupShader_DepthOrShadow();
9836                         }
9837                         RSurf_SetupDepthAndCulling();
9838                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9839                         if (rsurface.batchvertex3fbuffer)
9840                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9841                         else
9842                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9843                         RSurf_DrawBatch();
9844                 }
9845                 if (setup)
9846                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9847         }
9848
9849         for (i = 0;i < numsurfaces;i = j)
9850         {
9851                 j = i + 1;
9852                 surface = rsurface.modelsurfaces + surfacelist[i];
9853                 texture = surface->texture;
9854                 rsurface.texture = R_GetCurrentTexture(texture);
9855                 // scan ahead until we find a different texture
9856                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9857                 texturenumsurfaces = 0;
9858                 texturesurfacelist[texturenumsurfaces++] = surface;
9859                 if(FAKELIGHT_ENABLED)
9860                 {
9861                         rsurface.lightmaptexture = NULL;
9862                         rsurface.deluxemaptexture = NULL;
9863                         rsurface.uselightmaptexture = false;
9864                         for (;j < endsurface;j++)
9865                         {
9866                                 surface = rsurface.modelsurfaces + surfacelist[j];
9867                                 if (texture != surface->texture)
9868                                         break;
9869                                 texturesurfacelist[texturenumsurfaces++] = surface;
9870                         }
9871                 }
9872                 else
9873                 {
9874                         rsurface.lightmaptexture = surface->lightmaptexture;
9875                         rsurface.deluxemaptexture = surface->deluxemaptexture;
9876                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9877                         for (;j < endsurface;j++)
9878                         {
9879                                 surface = rsurface.modelsurfaces + surfacelist[j];
9880                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9881                                         break;
9882                                 texturesurfacelist[texturenumsurfaces++] = surface;
9883                         }
9884                 }
9885                 // render the range of surfaces
9886                 if (ent == r_refdef.scene.worldentity)
9887                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9888                 else
9889                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9890         }
9891         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9892 }
9893
9894 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9895 {
9896         // transparent surfaces get pushed off into the transparent queue
9897         int surfacelistindex;
9898         const msurface_t *surface;
9899         vec3_t tempcenter, center;
9900         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9901         {
9902                 surface = texturesurfacelist[surfacelistindex];
9903                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9904                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9905                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9906                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9907                 if (queueentity->transparent_offset) // transparent offset
9908                 {
9909                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9910                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9911                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9912                 }
9913                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9914         }
9915 }
9916
9917 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9918 {
9919         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9920                 return;
9921         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9922                 return;
9923         RSurf_SetupDepthAndCulling();
9924         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9925         if (rsurface.batchvertex3fbuffer)
9926                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9927         else
9928                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9929         RSurf_DrawBatch();
9930 }
9931
9932 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9933 {
9934         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9935         CHECKGLERROR
9936         if (depthonly)
9937                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9938         else if (prepass)
9939         {
9940                 if (!rsurface.texture->currentnumlayers)
9941                         return;
9942                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9943                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9944                 else
9945                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9946         }
9947         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9948                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9949         else if (!rsurface.texture->currentnumlayers)
9950                 return;
9951         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9952         {
9953                 // in the deferred case, transparent surfaces were queued during prepass
9954                 if (!r_shadow_usingdeferredprepass)
9955                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9956         }
9957         else
9958         {
9959                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9960                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9961         }
9962         CHECKGLERROR
9963 }
9964
9965 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9966 {
9967         int i, j;
9968         texture_t *texture;
9969         R_FrameData_SetMark();
9970         // break the surface list down into batches by texture and use of lightmapping
9971         for (i = 0;i < numsurfaces;i = j)
9972         {
9973                 j = i + 1;
9974                 // texture is the base texture pointer, rsurface.texture is the
9975                 // current frame/skin the texture is directing us to use (for example
9976                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9977                 // use skin 1 instead)
9978                 texture = surfacelist[i]->texture;
9979                 rsurface.texture = R_GetCurrentTexture(texture);
9980                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9981                 {
9982                         // if this texture is not the kind we want, skip ahead to the next one
9983                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9984                                 ;
9985                         continue;
9986                 }
9987                 if(FAKELIGHT_ENABLED || depthonly || prepass)
9988                 {
9989                         rsurface.lightmaptexture = NULL;
9990                         rsurface.deluxemaptexture = NULL;
9991                         rsurface.uselightmaptexture = false;
9992                         // simply scan ahead until we find a different texture or lightmap state
9993                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9994                                 ;
9995                 }
9996                 else
9997                 {
9998                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
9999                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10000                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10001                         // simply scan ahead until we find a different texture or lightmap state
10002                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10003                                 ;
10004                 }
10005                 // render the range of surfaces
10006                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10007         }
10008         R_FrameData_ReturnToMark();
10009 }
10010
10011 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10012 {
10013         CHECKGLERROR
10014         if (depthonly)
10015                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10016         else if (prepass)
10017         {
10018                 if (!rsurface.texture->currentnumlayers)
10019                         return;
10020                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10021                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10022                 else
10023                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10024         }
10025         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10026                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10027         else if (!rsurface.texture->currentnumlayers)
10028                 return;
10029         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10030         {
10031                 // in the deferred case, transparent surfaces were queued during prepass
10032                 if (!r_shadow_usingdeferredprepass)
10033                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10034         }
10035         else
10036         {
10037                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10038                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10039         }
10040         CHECKGLERROR
10041 }
10042
10043 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10044 {
10045         int i, j;
10046         texture_t *texture;
10047         R_FrameData_SetMark();
10048         // break the surface list down into batches by texture and use of lightmapping
10049         for (i = 0;i < numsurfaces;i = j)
10050         {
10051                 j = i + 1;
10052                 // texture is the base texture pointer, rsurface.texture is the
10053                 // current frame/skin the texture is directing us to use (for example
10054                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10055                 // use skin 1 instead)
10056                 texture = surfacelist[i]->texture;
10057                 rsurface.texture = R_GetCurrentTexture(texture);
10058                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10059                 {
10060                         // if this texture is not the kind we want, skip ahead to the next one
10061                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10062                                 ;
10063                         continue;
10064                 }
10065                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10066                 {
10067                         rsurface.lightmaptexture = NULL;
10068                         rsurface.deluxemaptexture = NULL;
10069                         rsurface.uselightmaptexture = false;
10070                         // simply scan ahead until we find a different texture or lightmap state
10071                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10072                                 ;
10073                 }
10074                 else
10075                 {
10076                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10077                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10078                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10079                         // simply scan ahead until we find a different texture or lightmap state
10080                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10081                                 ;
10082                 }
10083                 // render the range of surfaces
10084                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10085         }
10086         R_FrameData_ReturnToMark();
10087 }
10088
10089 float locboxvertex3f[6*4*3] =
10090 {
10091         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10092         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10093         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10094         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10095         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10096         1,0,0, 0,0,0, 0,1,0, 1,1,0
10097 };
10098
10099 unsigned short locboxelements[6*2*3] =
10100 {
10101          0, 1, 2, 0, 2, 3,
10102          4, 5, 6, 4, 6, 7,
10103          8, 9,10, 8,10,11,
10104         12,13,14, 12,14,15,
10105         16,17,18, 16,18,19,
10106         20,21,22, 20,22,23
10107 };
10108
10109 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10110 {
10111         int i, j;
10112         cl_locnode_t *loc = (cl_locnode_t *)ent;
10113         vec3_t mins, size;
10114         float vertex3f[6*4*3];
10115         CHECKGLERROR
10116         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10117         GL_DepthMask(false);
10118         GL_DepthRange(0, 1);
10119         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10120         GL_DepthTest(true);
10121         GL_CullFace(GL_NONE);
10122         R_EntityMatrix(&identitymatrix);
10123
10124 //      R_Mesh_ResetTextureState();
10125
10126         i = surfacelist[0];
10127         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10128                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10129                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10130                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10131
10132         if (VectorCompare(loc->mins, loc->maxs))
10133         {
10134                 VectorSet(size, 2, 2, 2);
10135                 VectorMA(loc->mins, -0.5f, size, mins);
10136         }
10137         else
10138         {
10139                 VectorCopy(loc->mins, mins);
10140                 VectorSubtract(loc->maxs, loc->mins, size);
10141         }
10142
10143         for (i = 0;i < 6*4*3;)
10144                 for (j = 0;j < 3;j++, i++)
10145                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10146
10147         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10148         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10149         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10150 }
10151
10152 void R_DrawLocs(void)
10153 {
10154         int index;
10155         cl_locnode_t *loc, *nearestloc;
10156         vec3_t center;
10157         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10158         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10159         {
10160                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10161                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10162         }
10163 }
10164
10165 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10166 {
10167         if (decalsystem->decals)
10168                 Mem_Free(decalsystem->decals);
10169         memset(decalsystem, 0, sizeof(*decalsystem));
10170 }
10171
10172 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)
10173 {
10174         tridecal_t *decal;
10175         tridecal_t *decals;
10176         int i;
10177
10178         // expand or initialize the system
10179         if (decalsystem->maxdecals <= decalsystem->numdecals)
10180         {
10181                 decalsystem_t old = *decalsystem;
10182                 qboolean useshortelements;
10183                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10184                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10185                 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)));
10186                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10187                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10188                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10189                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10190                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10191                 if (decalsystem->numdecals)
10192                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10193                 if (old.decals)
10194                         Mem_Free(old.decals);
10195                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10196                         decalsystem->element3i[i] = i;
10197                 if (useshortelements)
10198                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10199                                 decalsystem->element3s[i] = i;
10200         }
10201
10202         // grab a decal and search for another free slot for the next one
10203         decals = decalsystem->decals;
10204         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10205         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10206                 ;
10207         decalsystem->freedecal = i;
10208         if (decalsystem->numdecals <= i)
10209                 decalsystem->numdecals = i + 1;
10210
10211         // initialize the decal
10212         decal->lived = 0;
10213         decal->triangleindex = triangleindex;
10214         decal->surfaceindex = surfaceindex;
10215         decal->decalsequence = decalsequence;
10216         decal->color4f[0][0] = c0[0];
10217         decal->color4f[0][1] = c0[1];
10218         decal->color4f[0][2] = c0[2];
10219         decal->color4f[0][3] = 1;
10220         decal->color4f[1][0] = c1[0];
10221         decal->color4f[1][1] = c1[1];
10222         decal->color4f[1][2] = c1[2];
10223         decal->color4f[1][3] = 1;
10224         decal->color4f[2][0] = c2[0];
10225         decal->color4f[2][1] = c2[1];
10226         decal->color4f[2][2] = c2[2];
10227         decal->color4f[2][3] = 1;
10228         decal->vertex3f[0][0] = v0[0];
10229         decal->vertex3f[0][1] = v0[1];
10230         decal->vertex3f[0][2] = v0[2];
10231         decal->vertex3f[1][0] = v1[0];
10232         decal->vertex3f[1][1] = v1[1];
10233         decal->vertex3f[1][2] = v1[2];
10234         decal->vertex3f[2][0] = v2[0];
10235         decal->vertex3f[2][1] = v2[1];
10236         decal->vertex3f[2][2] = v2[2];
10237         decal->texcoord2f[0][0] = t0[0];
10238         decal->texcoord2f[0][1] = t0[1];
10239         decal->texcoord2f[1][0] = t1[0];
10240         decal->texcoord2f[1][1] = t1[1];
10241         decal->texcoord2f[2][0] = t2[0];
10242         decal->texcoord2f[2][1] = t2[1];
10243 }
10244
10245 extern cvar_t cl_decals_bias;
10246 extern cvar_t cl_decals_models;
10247 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10248 // baseparms, parms, temps
10249 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)
10250 {
10251         int cornerindex;
10252         int index;
10253         float v[9][3];
10254         const float *vertex3f;
10255         const float *normal3f;
10256         int numpoints;
10257         float points[2][9][3];
10258         float temp[3];
10259         float tc[9][2];
10260         float f;
10261         float c[9][4];
10262         const int *e;
10263
10264         e = rsurface.modelelement3i + 3*triangleindex;
10265
10266         vertex3f = rsurface.modelvertex3f;
10267         normal3f = rsurface.modelnormal3f;
10268
10269         for (cornerindex = 0;cornerindex < 3;cornerindex++)
10270         {
10271                 index = 3*e[cornerindex];
10272                 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10273         }
10274         // cull backfaces
10275         //TriangleNormal(v[0], v[1], v[2], normal);
10276         //if (DotProduct(normal, localnormal) < 0.0f)
10277         //      continue;
10278         // clip by each of the box planes formed from the projection matrix
10279         // if anything survives, we emit the decal
10280         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]);
10281         if (numpoints < 3)
10282                 return;
10283         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]);
10284         if (numpoints < 3)
10285                 return;
10286         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]);
10287         if (numpoints < 3)
10288                 return;
10289         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]);
10290         if (numpoints < 3)
10291                 return;
10292         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]);
10293         if (numpoints < 3)
10294                 return;
10295         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]);
10296         if (numpoints < 3)
10297                 return;
10298         // some part of the triangle survived, so we have to accept it...
10299         if (dynamic)
10300         {
10301                 // dynamic always uses the original triangle
10302                 numpoints = 3;
10303                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10304                 {
10305                         index = 3*e[cornerindex];
10306                         VectorCopy(vertex3f + index, v[cornerindex]);
10307                 }
10308         }
10309         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10310         {
10311                 // convert vertex positions to texcoords
10312                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10313                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10314                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10315                 // calculate distance fade from the projection origin
10316                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10317                 f = bound(0.0f, f, 1.0f);
10318                 c[cornerindex][0] = r * f;
10319                 c[cornerindex][1] = g * f;
10320                 c[cornerindex][2] = b * f;
10321                 c[cornerindex][3] = 1.0f;
10322                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10323         }
10324         if (dynamic)
10325                 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);
10326         else
10327                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10328                         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);
10329 }
10330 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)
10331 {
10332         matrix4x4_t projection;
10333         decalsystem_t *decalsystem;
10334         qboolean dynamic;
10335         dp_model_t *model;
10336         const msurface_t *surface;
10337         const msurface_t *surfaces;
10338         const int *surfacelist;
10339         const texture_t *texture;
10340         int numtriangles;
10341         int numsurfacelist;
10342         int surfacelistindex;
10343         int surfaceindex;
10344         int triangleindex;
10345         float localorigin[3];
10346         float localnormal[3];
10347         float localmins[3];
10348         float localmaxs[3];
10349         float localsize;
10350         //float normal[3];
10351         float planes[6][4];
10352         float angles[3];
10353         bih_t *bih;
10354         int bih_triangles_count;
10355         int bih_triangles[256];
10356         int bih_surfaces[256];
10357
10358         decalsystem = &ent->decalsystem;
10359         model = ent->model;
10360         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10361         {
10362                 R_DecalSystem_Reset(&ent->decalsystem);
10363                 return;
10364         }
10365
10366         if (!model->brush.data_leafs && !cl_decals_models.integer)
10367         {
10368                 if (decalsystem->model)
10369                         R_DecalSystem_Reset(decalsystem);
10370                 return;
10371         }
10372
10373         if (decalsystem->model != model)
10374                 R_DecalSystem_Reset(decalsystem);
10375         decalsystem->model = model;
10376
10377         RSurf_ActiveModelEntity(ent, true, false, false);
10378
10379         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10380         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10381         VectorNormalize(localnormal);
10382         localsize = worldsize*rsurface.inversematrixscale;
10383         localmins[0] = localorigin[0] - localsize;
10384         localmins[1] = localorigin[1] - localsize;
10385         localmins[2] = localorigin[2] - localsize;
10386         localmaxs[0] = localorigin[0] + localsize;
10387         localmaxs[1] = localorigin[1] + localsize;
10388         localmaxs[2] = localorigin[2] + localsize;
10389
10390         //VectorCopy(localnormal, planes[4]);
10391         //VectorVectors(planes[4], planes[2], planes[0]);
10392         AnglesFromVectors(angles, localnormal, NULL, false);
10393         AngleVectors(angles, planes[0], planes[2], planes[4]);
10394         VectorNegate(planes[0], planes[1]);
10395         VectorNegate(planes[2], planes[3]);
10396         VectorNegate(planes[4], planes[5]);
10397         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10398         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10399         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10400         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10401         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10402         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10403
10404 #if 1
10405 // works
10406 {
10407         matrix4x4_t forwardprojection;
10408         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10409         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10410 }
10411 #else
10412 // broken
10413 {
10414         float projectionvector[4][3];
10415         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10416         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10417         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10418         projectionvector[0][0] = planes[0][0] * ilocalsize;
10419         projectionvector[0][1] = planes[1][0] * ilocalsize;
10420         projectionvector[0][2] = planes[2][0] * ilocalsize;
10421         projectionvector[1][0] = planes[0][1] * ilocalsize;
10422         projectionvector[1][1] = planes[1][1] * ilocalsize;
10423         projectionvector[1][2] = planes[2][1] * ilocalsize;
10424         projectionvector[2][0] = planes[0][2] * ilocalsize;
10425         projectionvector[2][1] = planes[1][2] * ilocalsize;
10426         projectionvector[2][2] = planes[2][2] * ilocalsize;
10427         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10428         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10429         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10430         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10431 }
10432 #endif
10433
10434         dynamic = model->surfmesh.isanimated;
10435         numsurfacelist = model->nummodelsurfaces;
10436         surfacelist = model->sortedmodelsurfaces;
10437         surfaces = model->data_surfaces;
10438
10439         bih = NULL;
10440         bih_triangles_count = -1;
10441         if(!dynamic)
10442         {
10443                 if(model->render_bih.numleafs)
10444                         bih = &model->render_bih;
10445                 else if(model->collision_bih.numleafs)
10446                         bih = &model->collision_bih;
10447         }
10448         if(bih)
10449                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10450         if(bih_triangles_count == 0)
10451                 return;
10452         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10453                 return;
10454         if(bih_triangles_count > 0)
10455         {
10456                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10457                 {
10458                         surfaceindex = bih_surfaces[triangleindex];
10459                         surface = surfaces + surfaceindex;
10460                         texture = surface->texture;
10461                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10462                                 continue;
10463                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10464                                 continue;
10465                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10466                 }
10467         }
10468         else
10469         {
10470                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10471                 {
10472                         surfaceindex = surfacelist[surfacelistindex];
10473                         surface = surfaces + surfaceindex;
10474                         // check cull box first because it rejects more than any other check
10475                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10476                                 continue;
10477                         // skip transparent surfaces
10478                         texture = surface->texture;
10479                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10480                                 continue;
10481                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10482                                 continue;
10483                         numtriangles = surface->num_triangles;
10484                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10485                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10486                 }
10487         }
10488 }
10489
10490 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10491 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)
10492 {
10493         int renderentityindex;
10494         float worldmins[3];
10495         float worldmaxs[3];
10496         entity_render_t *ent;
10497
10498         if (!cl_decals_newsystem.integer)
10499                 return;
10500
10501         worldmins[0] = worldorigin[0] - worldsize;
10502         worldmins[1] = worldorigin[1] - worldsize;
10503         worldmins[2] = worldorigin[2] - worldsize;
10504         worldmaxs[0] = worldorigin[0] + worldsize;
10505         worldmaxs[1] = worldorigin[1] + worldsize;
10506         worldmaxs[2] = worldorigin[2] + worldsize;
10507
10508         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10509
10510         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10511         {
10512                 ent = r_refdef.scene.entities[renderentityindex];
10513                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10514                         continue;
10515
10516                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10517         }
10518 }
10519
10520 typedef struct r_decalsystem_splatqueue_s
10521 {
10522         vec3_t worldorigin;
10523         vec3_t worldnormal;
10524         float color[4];
10525         float tcrange[4];
10526         float worldsize;
10527         int decalsequence;
10528 }
10529 r_decalsystem_splatqueue_t;
10530
10531 int r_decalsystem_numqueued = 0;
10532 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10533
10534 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)
10535 {
10536         r_decalsystem_splatqueue_t *queue;
10537
10538         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10539                 return;
10540
10541         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10542         VectorCopy(worldorigin, queue->worldorigin);
10543         VectorCopy(worldnormal, queue->worldnormal);
10544         Vector4Set(queue->color, r, g, b, a);
10545         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10546         queue->worldsize = worldsize;
10547         queue->decalsequence = cl.decalsequence++;
10548 }
10549
10550 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10551 {
10552         int i;
10553         r_decalsystem_splatqueue_t *queue;
10554
10555         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10556                 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);
10557         r_decalsystem_numqueued = 0;
10558 }
10559
10560 extern cvar_t cl_decals_max;
10561 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10562 {
10563         int i;
10564         decalsystem_t *decalsystem = &ent->decalsystem;
10565         int numdecals;
10566         int killsequence;
10567         tridecal_t *decal;
10568         float frametime;
10569         float lifetime;
10570
10571         if (!decalsystem->numdecals)
10572                 return;
10573
10574         if (r_showsurfaces.integer)
10575                 return;
10576
10577         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10578         {
10579                 R_DecalSystem_Reset(decalsystem);
10580                 return;
10581         }
10582
10583         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10584         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10585
10586         if (decalsystem->lastupdatetime)
10587                 frametime = (cl.time - decalsystem->lastupdatetime);
10588         else
10589                 frametime = 0;
10590         decalsystem->lastupdatetime = cl.time;
10591         decal = decalsystem->decals;
10592         numdecals = decalsystem->numdecals;
10593
10594         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10595         {
10596                 if (decal->color4f[0][3])
10597                 {
10598                         decal->lived += frametime;
10599                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10600                         {
10601                                 memset(decal, 0, sizeof(*decal));
10602                                 if (decalsystem->freedecal > i)
10603                                         decalsystem->freedecal = i;
10604                         }
10605                 }
10606         }
10607         decal = decalsystem->decals;
10608         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10609                 numdecals--;
10610
10611         // collapse the array by shuffling the tail decals into the gaps
10612         for (;;)
10613         {
10614                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10615                         decalsystem->freedecal++;
10616                 if (decalsystem->freedecal == numdecals)
10617                         break;
10618                 decal[decalsystem->freedecal] = decal[--numdecals];
10619         }
10620
10621         decalsystem->numdecals = numdecals;
10622
10623         if (numdecals <= 0)
10624         {
10625                 // if there are no decals left, reset decalsystem
10626                 R_DecalSystem_Reset(decalsystem);
10627         }
10628 }
10629
10630 extern skinframe_t *decalskinframe;
10631 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10632 {
10633         int i;
10634         decalsystem_t *decalsystem = &ent->decalsystem;
10635         int numdecals;
10636         tridecal_t *decal;
10637         float faderate;
10638         float alpha;
10639         float *v3f;
10640         float *c4f;
10641         float *t2f;
10642         const int *e;
10643         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10644         int numtris = 0;
10645
10646         numdecals = decalsystem->numdecals;
10647         if (!numdecals)
10648                 return;
10649
10650         if (r_showsurfaces.integer)
10651                 return;
10652
10653         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10654         {
10655                 R_DecalSystem_Reset(decalsystem);
10656                 return;
10657         }
10658
10659         // if the model is static it doesn't matter what value we give for
10660         // wantnormals and wanttangents, so this logic uses only rules applicable
10661         // to a model, knowing that they are meaningless otherwise
10662         if (ent == r_refdef.scene.worldentity)
10663                 RSurf_ActiveWorldEntity();
10664         else
10665                 RSurf_ActiveModelEntity(ent, false, false, false);
10666
10667         decalsystem->lastupdatetime = cl.time;
10668         decal = decalsystem->decals;
10669
10670         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10671
10672         // update vertex positions for animated models
10673         v3f = decalsystem->vertex3f;
10674         c4f = decalsystem->color4f;
10675         t2f = decalsystem->texcoord2f;
10676         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10677         {
10678                 if (!decal->color4f[0][3])
10679                         continue;
10680
10681                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10682                         continue;
10683
10684                 // update color values for fading decals
10685                 if (decal->lived >= cl_decals_time.value)
10686                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10687                 else
10688                         alpha = 1.0f;
10689
10690                 c4f[ 0] = decal->color4f[0][0] * alpha;
10691                 c4f[ 1] = decal->color4f[0][1] * alpha;
10692                 c4f[ 2] = decal->color4f[0][2] * alpha;
10693                 c4f[ 3] = 1;
10694                 c4f[ 4] = decal->color4f[1][0] * alpha;
10695                 c4f[ 5] = decal->color4f[1][1] * alpha;
10696                 c4f[ 6] = decal->color4f[1][2] * alpha;
10697                 c4f[ 7] = 1;
10698                 c4f[ 8] = decal->color4f[2][0] * alpha;
10699                 c4f[ 9] = decal->color4f[2][1] * alpha;
10700                 c4f[10] = decal->color4f[2][2] * alpha;
10701                 c4f[11] = 1;
10702
10703                 t2f[0] = decal->texcoord2f[0][0];
10704                 t2f[1] = decal->texcoord2f[0][1];
10705                 t2f[2] = decal->texcoord2f[1][0];
10706                 t2f[3] = decal->texcoord2f[1][1];
10707                 t2f[4] = decal->texcoord2f[2][0];
10708                 t2f[5] = decal->texcoord2f[2][1];
10709
10710                 // update vertex positions for animated models
10711                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10712                 {
10713                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10714                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10715                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10716                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10717                 }
10718                 else
10719                 {
10720                         VectorCopy(decal->vertex3f[0], v3f);
10721                         VectorCopy(decal->vertex3f[1], v3f + 3);
10722                         VectorCopy(decal->vertex3f[2], v3f + 6);
10723                 }
10724
10725                 if (r_refdef.fogenabled)
10726                 {
10727                         alpha = RSurf_FogVertex(v3f);
10728                         VectorScale(c4f, alpha, c4f);
10729                         alpha = RSurf_FogVertex(v3f + 3);
10730                         VectorScale(c4f + 4, alpha, c4f + 4);
10731                         alpha = RSurf_FogVertex(v3f + 6);
10732                         VectorScale(c4f + 8, alpha, c4f + 8);
10733                 }
10734
10735                 v3f += 9;
10736                 c4f += 12;
10737                 t2f += 6;
10738                 numtris++;
10739         }
10740
10741         if (numtris > 0)
10742         {
10743                 r_refdef.stats.drawndecals += numtris;
10744
10745                 // now render the decals all at once
10746                 // (this assumes they all use one particle font texture!)
10747                 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);
10748 //              R_Mesh_ResetTextureState();
10749                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10750                 GL_DepthMask(false);
10751                 GL_DepthRange(0, 1);
10752                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10753                 GL_DepthTest(true);
10754                 GL_CullFace(GL_NONE);
10755                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10756                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10757                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10758         }
10759 }
10760
10761 static void R_DrawModelDecals(void)
10762 {
10763         int i, numdecals;
10764
10765         // fade faster when there are too many decals
10766         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10767         for (i = 0;i < r_refdef.scene.numentities;i++)
10768                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10769
10770         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10771         for (i = 0;i < r_refdef.scene.numentities;i++)
10772                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10773                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10774
10775         R_DecalSystem_ApplySplatEntitiesQueue();
10776
10777         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10778         for (i = 0;i < r_refdef.scene.numentities;i++)
10779                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10780
10781         r_refdef.stats.totaldecals += numdecals;
10782
10783         if (r_showsurfaces.integer)
10784                 return;
10785
10786         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10787
10788         for (i = 0;i < r_refdef.scene.numentities;i++)
10789         {
10790                 if (!r_refdef.viewcache.entityvisible[i])
10791                         continue;
10792                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10793                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10794         }
10795 }
10796
10797 extern cvar_t mod_collision_bih;
10798 void R_DrawDebugModel(void)
10799 {
10800         entity_render_t *ent = rsurface.entity;
10801         int i, j, k, l, flagsmask;
10802         const msurface_t *surface;
10803         dp_model_t *model = ent->model;
10804         vec3_t v;
10805
10806         switch(vid.renderpath)
10807         {
10808         case RENDERPATH_GL11:
10809         case RENDERPATH_GL13:
10810         case RENDERPATH_GL20:
10811                 break;
10812         case RENDERPATH_D3D9:
10813                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10814                 return;
10815         case RENDERPATH_D3D10:
10816                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10817                 return;
10818         case RENDERPATH_D3D11:
10819                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10820                 return;
10821         case RENDERPATH_SOFT:
10822                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10823                 return;
10824         case RENDERPATH_GLES2:
10825                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10826                 return;
10827         }
10828
10829         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10830
10831 //      R_Mesh_ResetTextureState();
10832         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10833         GL_DepthRange(0, 1);
10834         GL_DepthTest(!r_showdisabledepthtest.integer);
10835         GL_DepthMask(false);
10836         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10837
10838         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10839         {
10840                 int triangleindex;
10841                 int bihleafindex;
10842                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10843                 const q3mbrush_t *brush;
10844                 const bih_t *bih = &model->collision_bih;
10845                 const bih_leaf_t *bihleaf;
10846                 float vertex3f[3][3];
10847                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10848                 cullbox = false;
10849                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10850                 {
10851                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10852                                 continue;
10853                         switch (bihleaf->type)
10854                         {
10855                         case BIH_BRUSH:
10856                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10857                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10858                                 {
10859                                         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);
10860                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10861                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10862                                 }
10863                                 break;
10864                         case BIH_COLLISIONTRIANGLE:
10865                                 triangleindex = bihleaf->itemindex;
10866                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10867                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10868                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10869                                 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);
10870                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10871                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10872                                 break;
10873                         case BIH_RENDERTRIANGLE:
10874                                 triangleindex = bihleaf->itemindex;
10875                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10876                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10877                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10878                                 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);
10879                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10880                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10881                                 break;
10882                         }
10883                 }
10884         }
10885
10886         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10887
10888         if (r_showtris.integer || (r_shownormals.value != 0))
10889         {
10890                 if (r_showdisabledepthtest.integer)
10891                 {
10892                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10893                         GL_DepthMask(false);
10894                 }
10895                 else
10896                 {
10897                         GL_BlendFunc(GL_ONE, GL_ZERO);
10898                         GL_DepthMask(true);
10899                 }
10900                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10901                 {
10902                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10903                                 continue;
10904                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10905                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10906                         {
10907                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10908                                 if (r_showtris.value > 0)
10909                                 {
10910                                         if (!rsurface.texture->currentlayers->depthmask)
10911                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10912                                         else if (ent == r_refdef.scene.worldentity)
10913                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10914                                         else
10915                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10916                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10917                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10918                                         RSurf_DrawBatch();
10919                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10920                                         CHECKGLERROR
10921                                 }
10922                                 if (r_shownormals.value < 0)
10923                                 {
10924                                         qglBegin(GL_LINES);
10925                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10926                                         {
10927                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10928                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10929                                                 qglVertex3f(v[0], v[1], v[2]);
10930                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10931                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10932                                                 qglVertex3f(v[0], v[1], v[2]);
10933                                         }
10934                                         qglEnd();
10935                                         CHECKGLERROR
10936                                 }
10937                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10938                                 {
10939                                         qglBegin(GL_LINES);
10940                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10941                                         {
10942                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10943                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10944                                                 qglVertex3f(v[0], v[1], v[2]);
10945                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10946                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10947                                                 qglVertex3f(v[0], v[1], v[2]);
10948                                         }
10949                                         qglEnd();
10950                                         CHECKGLERROR
10951                                         qglBegin(GL_LINES);
10952                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10953                                         {
10954                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10955                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10956                                                 qglVertex3f(v[0], v[1], v[2]);
10957                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10958                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10959                                                 qglVertex3f(v[0], v[1], v[2]);
10960                                         }
10961                                         qglEnd();
10962                                         CHECKGLERROR
10963                                         qglBegin(GL_LINES);
10964                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10965                                         {
10966                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10967                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10968                                                 qglVertex3f(v[0], v[1], v[2]);
10969                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10970                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10971                                                 qglVertex3f(v[0], v[1], v[2]);
10972                                         }
10973                                         qglEnd();
10974                                         CHECKGLERROR
10975                                 }
10976                         }
10977                 }
10978                 rsurface.texture = NULL;
10979         }
10980 }
10981
10982 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10983 int r_maxsurfacelist = 0;
10984 const msurface_t **r_surfacelist = NULL;
10985 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10986 {
10987         int i, j, endj, flagsmask;
10988         dp_model_t *model = r_refdef.scene.worldmodel;
10989         msurface_t *surfaces;
10990         unsigned char *update;
10991         int numsurfacelist = 0;
10992         if (model == NULL)
10993                 return;
10994
10995         if (r_maxsurfacelist < model->num_surfaces)
10996         {
10997                 r_maxsurfacelist = model->num_surfaces;
10998                 if (r_surfacelist)
10999                         Mem_Free((msurface_t**)r_surfacelist);
11000                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11001         }
11002
11003         RSurf_ActiveWorldEntity();
11004
11005         surfaces = model->data_surfaces;
11006         update = model->brushq1.lightmapupdateflags;
11007
11008         // update light styles on this submodel
11009         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11010         {
11011                 model_brush_lightstyleinfo_t *style;
11012                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11013                 {
11014                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11015                         {
11016                                 int *list = style->surfacelist;
11017                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11018                                 for (j = 0;j < style->numsurfaces;j++)
11019                                         update[list[j]] = true;
11020                         }
11021                 }
11022         }
11023
11024         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11025
11026         if (debug)
11027         {
11028                 R_DrawDebugModel();
11029                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11030                 return;
11031         }
11032
11033         rsurface.lightmaptexture = NULL;
11034         rsurface.deluxemaptexture = NULL;
11035         rsurface.uselightmaptexture = false;
11036         rsurface.texture = NULL;
11037         rsurface.rtlight = NULL;
11038         numsurfacelist = 0;
11039         // add visible surfaces to draw list
11040         for (i = 0;i < model->nummodelsurfaces;i++)
11041         {
11042                 j = model->sortedmodelsurfaces[i];
11043                 if (r_refdef.viewcache.world_surfacevisible[j])
11044                         r_surfacelist[numsurfacelist++] = surfaces + j;
11045         }
11046         // update lightmaps if needed
11047         if (model->brushq1.firstrender)
11048         {
11049                 model->brushq1.firstrender = false;
11050                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11051                         if (update[j])
11052                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11053         }
11054         else if (update)
11055         {
11056                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11057                         if (r_refdef.viewcache.world_surfacevisible[j])
11058                                 if (update[j])
11059                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11060         }
11061         // don't do anything if there were no surfaces
11062         if (!numsurfacelist)
11063         {
11064                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11065                 return;
11066         }
11067         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11068
11069         // add to stats if desired
11070         if (r_speeds.integer && !skysurfaces && !depthonly)
11071         {
11072                 r_refdef.stats.world_surfaces += numsurfacelist;
11073                 for (j = 0;j < numsurfacelist;j++)
11074                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11075         }
11076
11077         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11078 }
11079
11080 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11081 {
11082         int i, j, endj, flagsmask;
11083         dp_model_t *model = ent->model;
11084         msurface_t *surfaces;
11085         unsigned char *update;
11086         int numsurfacelist = 0;
11087         if (model == NULL)
11088                 return;
11089
11090         if (r_maxsurfacelist < model->num_surfaces)
11091         {
11092                 r_maxsurfacelist = model->num_surfaces;
11093                 if (r_surfacelist)
11094                         Mem_Free((msurface_t **)r_surfacelist);
11095                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11096         }
11097
11098         // if the model is static it doesn't matter what value we give for
11099         // wantnormals and wanttangents, so this logic uses only rules applicable
11100         // to a model, knowing that they are meaningless otherwise
11101         if (ent == r_refdef.scene.worldentity)
11102                 RSurf_ActiveWorldEntity();
11103         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11104                 RSurf_ActiveModelEntity(ent, false, false, false);
11105         else if (prepass)
11106                 RSurf_ActiveModelEntity(ent, true, true, true);
11107         else if (depthonly)
11108         {
11109                 switch (vid.renderpath)
11110                 {
11111                 case RENDERPATH_GL20:
11112                 case RENDERPATH_D3D9:
11113                 case RENDERPATH_D3D10:
11114                 case RENDERPATH_D3D11:
11115                 case RENDERPATH_SOFT:
11116                 case RENDERPATH_GLES2:
11117                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11118                         break;
11119                 case RENDERPATH_GL13:
11120                 case RENDERPATH_GL11:
11121                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11122                         break;
11123                 }
11124         }
11125         else
11126         {
11127                 switch (vid.renderpath)
11128                 {
11129                 case RENDERPATH_GL20:
11130                 case RENDERPATH_D3D9:
11131                 case RENDERPATH_D3D10:
11132                 case RENDERPATH_D3D11:
11133                 case RENDERPATH_SOFT:
11134                 case RENDERPATH_GLES2:
11135                         RSurf_ActiveModelEntity(ent, true, true, false);
11136                         break;
11137                 case RENDERPATH_GL13:
11138                 case RENDERPATH_GL11:
11139                         RSurf_ActiveModelEntity(ent, true, false, false);
11140                         break;
11141                 }
11142         }
11143
11144         surfaces = model->data_surfaces;
11145         update = model->brushq1.lightmapupdateflags;
11146
11147         // update light styles
11148         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11149         {
11150                 model_brush_lightstyleinfo_t *style;
11151                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11152                 {
11153                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11154                         {
11155                                 int *list = style->surfacelist;
11156                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11157                                 for (j = 0;j < style->numsurfaces;j++)
11158                                         update[list[j]] = true;
11159                         }
11160                 }
11161         }
11162
11163         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11164
11165         if (debug)
11166         {
11167                 R_DrawDebugModel();
11168                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11169                 return;
11170         }
11171
11172         rsurface.lightmaptexture = NULL;
11173         rsurface.deluxemaptexture = NULL;
11174         rsurface.uselightmaptexture = false;
11175         rsurface.texture = NULL;
11176         rsurface.rtlight = NULL;
11177         numsurfacelist = 0;
11178         // add visible surfaces to draw list
11179         for (i = 0;i < model->nummodelsurfaces;i++)
11180                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11181         // don't do anything if there were no surfaces
11182         if (!numsurfacelist)
11183         {
11184                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11185                 return;
11186         }
11187         // update lightmaps if needed
11188         if (update)
11189         {
11190                 int updated = 0;
11191                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11192                 {
11193                         if (update[j])
11194                         {
11195                                 updated++;
11196                                 R_BuildLightMap(ent, surfaces + j);
11197                         }
11198                 }
11199         }
11200         if (update)
11201                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11202                         if (update[j])
11203                                 R_BuildLightMap(ent, surfaces + j);
11204         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11205
11206         // add to stats if desired
11207         if (r_speeds.integer && !skysurfaces && !depthonly)
11208         {
11209                 r_refdef.stats.entities_surfaces += numsurfacelist;
11210                 for (j = 0;j < numsurfacelist;j++)
11211                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11212         }
11213
11214         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11215 }
11216
11217 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11218 {
11219         static texture_t texture;
11220         static msurface_t surface;
11221         const msurface_t *surfacelist = &surface;
11222
11223         // fake enough texture and surface state to render this geometry
11224
11225         texture.update_lastrenderframe = -1; // regenerate this texture
11226         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11227         texture.currentskinframe = skinframe;
11228         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11229         texture.offsetmapping = OFFSETMAPPING_OFF;
11230         texture.offsetscale = 1;
11231         texture.specularscalemod = 1;
11232         texture.specularpowermod = 1;
11233
11234         surface.texture = &texture;
11235         surface.num_triangles = numtriangles;
11236         surface.num_firsttriangle = firsttriangle;
11237         surface.num_vertices = numvertices;
11238         surface.num_firstvertex = firstvertex;
11239
11240         // now render it
11241         rsurface.texture = R_GetCurrentTexture(surface.texture);
11242         rsurface.lightmaptexture = NULL;
11243         rsurface.deluxemaptexture = NULL;
11244         rsurface.uselightmaptexture = false;
11245         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11246 }
11247
11248 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)
11249 {
11250         static msurface_t surface;
11251         const msurface_t *surfacelist = &surface;
11252
11253         // fake enough texture and surface state to render this geometry
11254         surface.texture = texture;
11255         surface.num_triangles = numtriangles;
11256         surface.num_firsttriangle = firsttriangle;
11257         surface.num_vertices = numvertices;
11258         surface.num_firstvertex = firstvertex;
11259
11260         // now render it
11261         rsurface.texture = R_GetCurrentTexture(surface.texture);
11262         rsurface.lightmaptexture = NULL;
11263         rsurface.deluxemaptexture = NULL;
11264         rsurface.uselightmaptexture = false;
11265         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11266 }