]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
add cvars r_glsl_offsetmapping_steps and r_glsl_offsetmapping_reliefmapping_steps
[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_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
146 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
147 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
148 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
149 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
150 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)"};
151 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)"};
152 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)"};
153 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)"};
154 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)"};
155 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)"};
156 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)"};
157 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)"};
158
159 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)"};
160 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
161 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"};
162 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
163 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
164 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
165
166 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
167 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
168 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
169 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
170
171 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
172 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
173 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
174 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
175 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
176 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
177 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
178
179 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
180 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
181 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
182 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)"};
183 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
184 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
185 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
186 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
187 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
188 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
189
190 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"};
191
192 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"};
193
194 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
195
196 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
197 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"};
198 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
199 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
200 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
201 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
202 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)"};
203 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
204 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
205
206 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
207 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"};
208
209 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)"};
210
211 extern cvar_t v_glslgamma;
212
213 extern qboolean v_flipped_state;
214
215 static struct r_bloomstate_s
216 {
217         qboolean enabled;
218         qboolean hdr;
219
220         int bloomwidth, bloomheight;
221
222         int screentexturewidth, screentextureheight;
223         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
224
225         int bloomtexturewidth, bloomtextureheight;
226         rtexture_t *texture_bloom;
227
228         // arrays for rendering the screen passes
229         float screentexcoord2f[8];
230         float bloomtexcoord2f[8];
231         float offsettexcoord2f[8];
232
233         r_viewport_t viewport;
234 }
235 r_bloomstate;
236
237 r_waterstate_t r_waterstate;
238
239 /// shadow volume bsp struct with automatically growing nodes buffer
240 svbsp_t r_svbsp;
241
242 rtexture_t *r_texture_blanknormalmap;
243 rtexture_t *r_texture_white;
244 rtexture_t *r_texture_grey128;
245 rtexture_t *r_texture_black;
246 rtexture_t *r_texture_notexture;
247 rtexture_t *r_texture_whitecube;
248 rtexture_t *r_texture_normalizationcube;
249 rtexture_t *r_texture_fogattenuation;
250 rtexture_t *r_texture_fogheighttexture;
251 rtexture_t *r_texture_gammaramps;
252 unsigned int r_texture_gammaramps_serial;
253 //rtexture_t *r_texture_fogintensity;
254 rtexture_t *r_texture_reflectcube;
255
256 // TODO: hash lookups?
257 typedef struct cubemapinfo_s
258 {
259         char basename[64];
260         rtexture_t *texture;
261 }
262 cubemapinfo_t;
263
264 int r_texture_numcubemaps;
265 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
266
267 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
268 unsigned int r_numqueries;
269 unsigned int r_maxqueries;
270
271 typedef struct r_qwskincache_s
272 {
273         char name[MAX_QPATH];
274         skinframe_t *skinframe;
275 }
276 r_qwskincache_t;
277
278 static r_qwskincache_t *r_qwskincache;
279 static int r_qwskincache_size;
280
281 /// vertex coordinates for a quad that covers the screen exactly
282 extern const float r_screenvertex3f[12];
283 extern const float r_d3dscreenvertex3f[12];
284 const float r_screenvertex3f[12] =
285 {
286         0, 0, 0,
287         1, 0, 0,
288         1, 1, 0,
289         0, 1, 0
290 };
291 const float r_d3dscreenvertex3f[12] =
292 {
293         0, 1, 0,
294         1, 1, 0,
295         1, 0, 0,
296         0, 0, 0
297 };
298
299 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
300 {
301         int i;
302         for (i = 0;i < verts;i++)
303         {
304                 out[0] = in[0] * r;
305                 out[1] = in[1] * g;
306                 out[2] = in[2] * b;
307                 out[3] = in[3];
308                 in += 4;
309                 out += 4;
310         }
311 }
312
313 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
314 {
315         int i;
316         for (i = 0;i < verts;i++)
317         {
318                 out[0] = r;
319                 out[1] = g;
320                 out[2] = b;
321                 out[3] = a;
322                 out += 4;
323         }
324 }
325
326 // FIXME: move this to client?
327 void FOG_clear(void)
328 {
329         if (gamemode == GAME_NEHAHRA)
330         {
331                 Cvar_Set("gl_fogenable", "0");
332                 Cvar_Set("gl_fogdensity", "0.2");
333                 Cvar_Set("gl_fogred", "0.3");
334                 Cvar_Set("gl_foggreen", "0.3");
335                 Cvar_Set("gl_fogblue", "0.3");
336         }
337         r_refdef.fog_density = 0;
338         r_refdef.fog_red = 0;
339         r_refdef.fog_green = 0;
340         r_refdef.fog_blue = 0;
341         r_refdef.fog_alpha = 1;
342         r_refdef.fog_start = 0;
343         r_refdef.fog_end = 16384;
344         r_refdef.fog_height = 1<<30;
345         r_refdef.fog_fadedepth = 128;
346         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
347 }
348
349 static void R_BuildBlankTextures(void)
350 {
351         unsigned char data[4];
352         data[2] = 128; // normal X
353         data[1] = 128; // normal Y
354         data[0] = 255; // normal Z
355         data[3] = 128; // height
356         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
357         data[0] = 255;
358         data[1] = 255;
359         data[2] = 255;
360         data[3] = 255;
361         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
362         data[0] = 128;
363         data[1] = 128;
364         data[2] = 128;
365         data[3] = 255;
366         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
367         data[0] = 0;
368         data[1] = 0;
369         data[2] = 0;
370         data[3] = 255;
371         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
372 }
373
374 static void R_BuildNoTexture(void)
375 {
376         int x, y;
377         unsigned char pix[16][16][4];
378         // this makes a light grey/dark grey checkerboard texture
379         for (y = 0;y < 16;y++)
380         {
381                 for (x = 0;x < 16;x++)
382                 {
383                         if ((y < 8) ^ (x < 8))
384                         {
385                                 pix[y][x][0] = 128;
386                                 pix[y][x][1] = 128;
387                                 pix[y][x][2] = 128;
388                                 pix[y][x][3] = 255;
389                         }
390                         else
391                         {
392                                 pix[y][x][0] = 64;
393                                 pix[y][x][1] = 64;
394                                 pix[y][x][2] = 64;
395                                 pix[y][x][3] = 255;
396                         }
397                 }
398         }
399         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
400 }
401
402 static void R_BuildWhiteCube(void)
403 {
404         unsigned char data[6*1*1*4];
405         memset(data, 255, sizeof(data));
406         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
407 }
408
409 static void R_BuildNormalizationCube(void)
410 {
411         int x, y, side;
412         vec3_t v;
413         vec_t s, t, intensity;
414 #define NORMSIZE 64
415         unsigned char *data;
416         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
417         for (side = 0;side < 6;side++)
418         {
419                 for (y = 0;y < NORMSIZE;y++)
420                 {
421                         for (x = 0;x < NORMSIZE;x++)
422                         {
423                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
424                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
425                                 switch(side)
426                                 {
427                                 default:
428                                 case 0:
429                                         v[0] = 1;
430                                         v[1] = -t;
431                                         v[2] = -s;
432                                         break;
433                                 case 1:
434                                         v[0] = -1;
435                                         v[1] = -t;
436                                         v[2] = s;
437                                         break;
438                                 case 2:
439                                         v[0] = s;
440                                         v[1] = 1;
441                                         v[2] = t;
442                                         break;
443                                 case 3:
444                                         v[0] = s;
445                                         v[1] = -1;
446                                         v[2] = -t;
447                                         break;
448                                 case 4:
449                                         v[0] = s;
450                                         v[1] = -t;
451                                         v[2] = 1;
452                                         break;
453                                 case 5:
454                                         v[0] = -s;
455                                         v[1] = -t;
456                                         v[2] = -1;
457                                         break;
458                                 }
459                                 intensity = 127.0f / sqrt(DotProduct(v, v));
460                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
461                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
462                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
463                                 data[((side*64+y)*64+x)*4+3] = 255;
464                         }
465                 }
466         }
467         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
468         Mem_Free(data);
469 }
470
471 static void R_BuildFogTexture(void)
472 {
473         int x, b;
474 #define FOGWIDTH 256
475         unsigned char data1[FOGWIDTH][4];
476         //unsigned char data2[FOGWIDTH][4];
477         double d, r, alpha;
478
479         r_refdef.fogmasktable_start = r_refdef.fog_start;
480         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
481         r_refdef.fogmasktable_range = r_refdef.fogrange;
482         r_refdef.fogmasktable_density = r_refdef.fog_density;
483
484         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
485         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
486         {
487                 d = (x * r - r_refdef.fogmasktable_start);
488                 if(developer_extra.integer)
489                         Con_DPrintf("%f ", d);
490                 d = max(0, d);
491                 if (r_fog_exp2.integer)
492                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
493                 else
494                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
495                 if(developer_extra.integer)
496                         Con_DPrintf(" : %f ", alpha);
497                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
498                 if(developer_extra.integer)
499                         Con_DPrintf(" = %f\n", alpha);
500                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
501         }
502
503         for (x = 0;x < FOGWIDTH;x++)
504         {
505                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
506                 data1[x][0] = b;
507                 data1[x][1] = b;
508                 data1[x][2] = b;
509                 data1[x][3] = 255;
510                 //data2[x][0] = 255 - b;
511                 //data2[x][1] = 255 - b;
512                 //data2[x][2] = 255 - b;
513                 //data2[x][3] = 255;
514         }
515         if (r_texture_fogattenuation)
516         {
517                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
518                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
519         }
520         else
521         {
522                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
523                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
524         }
525 }
526
527 static void R_BuildFogHeightTexture(void)
528 {
529         unsigned char *inpixels;
530         int size;
531         int x;
532         int y;
533         int j;
534         float c[4];
535         float f;
536         inpixels = NULL;
537         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
538         if (r_refdef.fogheighttexturename[0])
539                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
540         if (!inpixels)
541         {
542                 r_refdef.fog_height_tablesize = 0;
543                 if (r_texture_fogheighttexture)
544                         R_FreeTexture(r_texture_fogheighttexture);
545                 r_texture_fogheighttexture = NULL;
546                 if (r_refdef.fog_height_table2d)
547                         Mem_Free(r_refdef.fog_height_table2d);
548                 r_refdef.fog_height_table2d = NULL;
549                 if (r_refdef.fog_height_table1d)
550                         Mem_Free(r_refdef.fog_height_table1d);
551                 r_refdef.fog_height_table1d = NULL;
552                 return;
553         }
554         size = image_width;
555         r_refdef.fog_height_tablesize = size;
556         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
557         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
558         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
559         Mem_Free(inpixels);
560         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
561         // average fog color table accounting for every fog layer between a point
562         // and the camera.  (Note: attenuation is handled separately!)
563         for (y = 0;y < size;y++)
564         {
565                 for (x = 0;x < size;x++)
566                 {
567                         Vector4Clear(c);
568                         f = 0;
569                         if (x < y)
570                         {
571                                 for (j = x;j <= y;j++)
572                                 {
573                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
574                                         f++;
575                                 }
576                         }
577                         else
578                         {
579                                 for (j = x;j >= y;j--)
580                                 {
581                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
582                                         f++;
583                                 }
584                         }
585                         f = 1.0f / f;
586                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
587                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
588                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
589                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
590                 }
591         }
592         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
593 }
594
595 //=======================================================================================================================================================
596
597 static const char *builtinshaderstring =
598 #include "shader_glsl.h"
599 ;
600
601 const char *builtinhlslshaderstring =
602 #include "shader_hlsl.h"
603 ;
604
605 char *glslshaderstring = NULL;
606 char *hlslshaderstring = NULL;
607
608 //=======================================================================================================================================================
609
610 typedef struct shaderpermutationinfo_s
611 {
612         const char *pretext;
613         const char *name;
614 }
615 shaderpermutationinfo_t;
616
617 typedef struct shadermodeinfo_s
618 {
619         const char *vertexfilename;
620         const char *geometryfilename;
621         const char *fragmentfilename;
622         const char *pretext;
623         const char *name;
624 }
625 shadermodeinfo_t;
626
627 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
628 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
629 {
630         {"#define USEDIFFUSE\n", " diffuse"},
631         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
632         {"#define USEVIEWTINT\n", " viewtint"},
633         {"#define USECOLORMAPPING\n", " colormapping"},
634         {"#define USESATURATION\n", " saturation"},
635         {"#define USEFOGINSIDE\n", " foginside"},
636         {"#define USEFOGOUTSIDE\n", " fogoutside"},
637         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
638         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
639         {"#define USEGAMMARAMPS\n", " gammaramps"},
640         {"#define USECUBEFILTER\n", " cubefilter"},
641         {"#define USEGLOW\n", " glow"},
642         {"#define USEBLOOM\n", " bloom"},
643         {"#define USESPECULAR\n", " specular"},
644         {"#define USEPOSTPROCESSING\n", " postprocessing"},
645         {"#define USEREFLECTION\n", " reflection"},
646         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
647         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
648         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
649         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
650         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
651         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
652         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
653         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
654         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
655         {"#define USEALPHAKILL\n", " alphakill"},
656         {"#define USEREFLECTCUBE\n", " reflectcube"},
657         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
658         {"#define USEBOUNCEGRID\n", " bouncegrid"},
659 };
660
661 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
662 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
663 {
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
666         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
680 };
681
682 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
683 {
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
700 };
701
702 struct r_glsl_permutation_s;
703 typedef struct r_glsl_permutation_s
704 {
705         /// hash lookup data
706         struct r_glsl_permutation_s *hashnext;
707         unsigned int mode;
708         unsigned int permutation;
709
710         /// indicates if we have tried compiling this permutation already
711         qboolean compiled;
712         /// 0 if compilation failed
713         int program;
714         // texture units assigned to each detected uniform
715         int tex_Texture_First;
716         int tex_Texture_Second;
717         int tex_Texture_GammaRamps;
718         int tex_Texture_Normal;
719         int tex_Texture_Color;
720         int tex_Texture_Gloss;
721         int tex_Texture_Glow;
722         int tex_Texture_SecondaryNormal;
723         int tex_Texture_SecondaryColor;
724         int tex_Texture_SecondaryGloss;
725         int tex_Texture_SecondaryGlow;
726         int tex_Texture_Pants;
727         int tex_Texture_Shirt;
728         int tex_Texture_FogHeightTexture;
729         int tex_Texture_FogMask;
730         int tex_Texture_Lightmap;
731         int tex_Texture_Deluxemap;
732         int tex_Texture_Attenuation;
733         int tex_Texture_Cube;
734         int tex_Texture_Refraction;
735         int tex_Texture_Reflection;
736         int tex_Texture_ShadowMap2D;
737         int tex_Texture_CubeProjection;
738         int tex_Texture_ScreenDepth;
739         int tex_Texture_ScreenNormalMap;
740         int tex_Texture_ScreenDiffuse;
741         int tex_Texture_ScreenSpecular;
742         int tex_Texture_ReflectMask;
743         int tex_Texture_ReflectCube;
744         int tex_Texture_BounceGrid;
745         /// locations of detected uniforms in program object, or -1 if not found
746         int loc_Texture_First;
747         int loc_Texture_Second;
748         int loc_Texture_GammaRamps;
749         int loc_Texture_Normal;
750         int loc_Texture_Color;
751         int loc_Texture_Gloss;
752         int loc_Texture_Glow;
753         int loc_Texture_SecondaryNormal;
754         int loc_Texture_SecondaryColor;
755         int loc_Texture_SecondaryGloss;
756         int loc_Texture_SecondaryGlow;
757         int loc_Texture_Pants;
758         int loc_Texture_Shirt;
759         int loc_Texture_FogHeightTexture;
760         int loc_Texture_FogMask;
761         int loc_Texture_Lightmap;
762         int loc_Texture_Deluxemap;
763         int loc_Texture_Attenuation;
764         int loc_Texture_Cube;
765         int loc_Texture_Refraction;
766         int loc_Texture_Reflection;
767         int loc_Texture_ShadowMap2D;
768         int loc_Texture_CubeProjection;
769         int loc_Texture_ScreenDepth;
770         int loc_Texture_ScreenNormalMap;
771         int loc_Texture_ScreenDiffuse;
772         int loc_Texture_ScreenSpecular;
773         int loc_Texture_ReflectMask;
774         int loc_Texture_ReflectCube;
775         int loc_Texture_BounceGrid;
776         int loc_Alpha;
777         int loc_BloomBlur_Parameters;
778         int loc_ClientTime;
779         int loc_Color_Ambient;
780         int loc_Color_Diffuse;
781         int loc_Color_Specular;
782         int loc_Color_Glow;
783         int loc_Color_Pants;
784         int loc_Color_Shirt;
785         int loc_DeferredColor_Ambient;
786         int loc_DeferredColor_Diffuse;
787         int loc_DeferredColor_Specular;
788         int loc_DeferredMod_Diffuse;
789         int loc_DeferredMod_Specular;
790         int loc_DistortScaleRefractReflect;
791         int loc_EyePosition;
792         int loc_FogColor;
793         int loc_FogHeightFade;
794         int loc_FogPlane;
795         int loc_FogPlaneViewDist;
796         int loc_FogRangeRecip;
797         int loc_LightColor;
798         int loc_LightDir;
799         int loc_LightPosition;
800         int loc_OffsetMapping_ScaleSteps;
801         int loc_PixelSize;
802         int loc_ReflectColor;
803         int loc_ReflectFactor;
804         int loc_ReflectOffset;
805         int loc_RefractColor;
806         int loc_Saturation;
807         int loc_ScreenCenterRefractReflect;
808         int loc_ScreenScaleRefractReflect;
809         int loc_ScreenToDepth;
810         int loc_ShadowMap_Parameters;
811         int loc_ShadowMap_TextureScale;
812         int loc_SpecularPower;
813         int loc_UserVec1;
814         int loc_UserVec2;
815         int loc_UserVec3;
816         int loc_UserVec4;
817         int loc_ViewTintColor;
818         int loc_ViewToLight;
819         int loc_ModelToLight;
820         int loc_TexMatrix;
821         int loc_BackgroundTexMatrix;
822         int loc_ModelViewProjectionMatrix;
823         int loc_ModelViewMatrix;
824         int loc_PixelToScreenTexCoord;
825         int loc_ModelToReflectCube;
826         int loc_ShadowMapMatrix;
827         int loc_BloomColorSubtract;
828         int loc_NormalmapScrollBlend;
829         int loc_BounceGridMatrix;
830         int loc_BounceGridIntensity;
831 }
832 r_glsl_permutation_t;
833
834 #define SHADERPERMUTATION_HASHSIZE 256
835
836
837 // non-degradable "lightweight" shader parameters to keep the permutations simpler
838 // these can NOT degrade! only use for simple stuff
839 enum
840 {
841         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
842         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
843         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
844         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
845         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
846         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
847 };
848 #define SHADERSTATICPARMS_COUNT 6
849
850 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
851 static int shaderstaticparms_count = 0;
852
853 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
854 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
855 qboolean R_CompileShader_CheckStaticParms(void)
856 {
857         static int r_compileshader_staticparms_save[1];
858         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
859         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
860
861         // detect all
862         if (r_glsl_saturation_redcompensate.integer)
863                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
864         if (r_shadow_glossexact.integer)
865                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
866         if (r_glsl_postprocess.integer)
867         {
868                 if (r_glsl_postprocess_uservec1_enable.integer)
869                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
870                 if (r_glsl_postprocess_uservec2_enable.integer)
871                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
872                 if (r_glsl_postprocess_uservec3_enable.integer)
873                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
874                 if (r_glsl_postprocess_uservec4_enable.integer)
875                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
876         }
877         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
878 }
879
880 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
881         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
882                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
883         else \
884                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
885 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
886 {
887         shaderstaticparms_count = 0;
888
889         // emit all
890         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
891         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
892         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
893         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
894         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
895         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
896 }
897
898 /// information about each possible shader permutation
899 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
900 /// currently selected permutation
901 r_glsl_permutation_t *r_glsl_permutation;
902 /// storage for permutations linked in the hash table
903 memexpandablearray_t r_glsl_permutationarray;
904
905 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
906 {
907         //unsigned int hashdepth = 0;
908         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
909         r_glsl_permutation_t *p;
910         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
911         {
912                 if (p->mode == mode && p->permutation == permutation)
913                 {
914                         //if (hashdepth > 10)
915                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
916                         return p;
917                 }
918                 //hashdepth++;
919         }
920         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
921         p->mode = mode;
922         p->permutation = permutation;
923         p->hashnext = r_glsl_permutationhash[mode][hashindex];
924         r_glsl_permutationhash[mode][hashindex] = p;
925         //if (hashdepth > 10)
926         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
927         return p;
928 }
929
930 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
931 {
932         char *shaderstring;
933         if (!filename || !filename[0])
934                 return NULL;
935         if (!strcmp(filename, "glsl/default.glsl"))
936         {
937                 if (!glslshaderstring)
938                 {
939                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
940                         if (glslshaderstring)
941                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
942                         else
943                                 glslshaderstring = (char *)builtinshaderstring;
944                 }
945                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
946                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
947                 return shaderstring;
948         }
949         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
950         if (shaderstring)
951         {
952                 if (printfromdisknotice)
953                         Con_DPrintf("from disk %s... ", filename);
954                 return shaderstring;
955         }
956         return shaderstring;
957 }
958
959 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
960 {
961         int i;
962         int sampler;
963         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
964         char *vertexstring, *geometrystring, *fragmentstring;
965         char permutationname[256];
966         int vertstrings_count = 0;
967         int geomstrings_count = 0;
968         int fragstrings_count = 0;
969         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
970         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
971         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
972
973         if (p->compiled)
974                 return;
975         p->compiled = true;
976         p->program = 0;
977
978         permutationname[0] = 0;
979         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
980         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
981         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
982
983         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
984
985         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
986         if(vid.support.gl20shaders130)
987         {
988                 vertstrings_list[vertstrings_count++] = "#version 130\n";
989                 geomstrings_list[geomstrings_count++] = "#version 130\n";
990                 fragstrings_list[fragstrings_count++] = "#version 130\n";
991         }
992
993         // the first pretext is which type of shader to compile as
994         // (later these will all be bound together as a program object)
995         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
996         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
997         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
998
999         // the second pretext is the mode (for example a light source)
1000         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1001         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1002         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1003         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1004
1005         // now add all the permutation pretexts
1006         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1007         {
1008                 if (permutation & (1<<i))
1009                 {
1010                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1011                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1012                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1013                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1014                 }
1015                 else
1016                 {
1017                         // keep line numbers correct
1018                         vertstrings_list[vertstrings_count++] = "\n";
1019                         geomstrings_list[geomstrings_count++] = "\n";
1020                         fragstrings_list[fragstrings_count++] = "\n";
1021                 }
1022         }
1023
1024         // add static parms
1025         R_CompileShader_AddStaticParms(mode, permutation);
1026         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1027         vertstrings_count += shaderstaticparms_count;
1028         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1029         geomstrings_count += shaderstaticparms_count;
1030         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1031         fragstrings_count += shaderstaticparms_count;
1032
1033         // now append the shader text itself
1034         vertstrings_list[vertstrings_count++] = vertexstring;
1035         geomstrings_list[geomstrings_count++] = geometrystring;
1036         fragstrings_list[fragstrings_count++] = fragmentstring;
1037
1038         // if any sources were NULL, clear the respective list
1039         if (!vertexstring)
1040                 vertstrings_count = 0;
1041         if (!geometrystring)
1042                 geomstrings_count = 0;
1043         if (!fragmentstring)
1044                 fragstrings_count = 0;
1045
1046         // compile the shader program
1047         if (vertstrings_count + geomstrings_count + fragstrings_count)
1048                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1049         if (p->program)
1050         {
1051                 CHECKGLERROR
1052                 qglUseProgram(p->program);CHECKGLERROR
1053                 // look up all the uniform variable names we care about, so we don't
1054                 // have to look them up every time we set them
1055
1056                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1057                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1058                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1059                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1060                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1061                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1062                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1063                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1064                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1065                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1066                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1067                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1068                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1069                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1070                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1071                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1072                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1073                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1074                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1075                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1076                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1077                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1078                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1079                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1080                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1081                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1082                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1083                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1084                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1085                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1086                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1087                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1088                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1089                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1090                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1091                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1092                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1093                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1094                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1095                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1096                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1097                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1098                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1099                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1100                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1101                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1102                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1103                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1104                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1105                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1106                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1107                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1108                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1109                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1110                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1111                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1112                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1113                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1114                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1115                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1116                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1117                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1118                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1119                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1120                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1121                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1122                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1123                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1124                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1125                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1126                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1127                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1128                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1129                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1130                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1131                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1132                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1133                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1134                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1135                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1136                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1137                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1138                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1139                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1140                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1141                 // initialize the samplers to refer to the texture units we use
1142                 p->tex_Texture_First = -1;
1143                 p->tex_Texture_Second = -1;
1144                 p->tex_Texture_GammaRamps = -1;
1145                 p->tex_Texture_Normal = -1;
1146                 p->tex_Texture_Color = -1;
1147                 p->tex_Texture_Gloss = -1;
1148                 p->tex_Texture_Glow = -1;
1149                 p->tex_Texture_SecondaryNormal = -1;
1150                 p->tex_Texture_SecondaryColor = -1;
1151                 p->tex_Texture_SecondaryGloss = -1;
1152                 p->tex_Texture_SecondaryGlow = -1;
1153                 p->tex_Texture_Pants = -1;
1154                 p->tex_Texture_Shirt = -1;
1155                 p->tex_Texture_FogHeightTexture = -1;
1156                 p->tex_Texture_FogMask = -1;
1157                 p->tex_Texture_Lightmap = -1;
1158                 p->tex_Texture_Deluxemap = -1;
1159                 p->tex_Texture_Attenuation = -1;
1160                 p->tex_Texture_Cube = -1;
1161                 p->tex_Texture_Refraction = -1;
1162                 p->tex_Texture_Reflection = -1;
1163                 p->tex_Texture_ShadowMap2D = -1;
1164                 p->tex_Texture_CubeProjection = -1;
1165                 p->tex_Texture_ScreenDepth = -1;
1166                 p->tex_Texture_ScreenNormalMap = -1;
1167                 p->tex_Texture_ScreenDiffuse = -1;
1168                 p->tex_Texture_ScreenSpecular = -1;
1169                 p->tex_Texture_ReflectMask = -1;
1170                 p->tex_Texture_ReflectCube = -1;
1171                 p->tex_Texture_BounceGrid = -1;
1172                 sampler = 0;
1173                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1174                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1175                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1176                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1177                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1178                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1179                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1180                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1181                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1182                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1183                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1184                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1185                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1186                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1187                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1188                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1189                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1190                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1191                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1192                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1193                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1194                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1195                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1196                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1197                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1198                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1199                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1200                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1201                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1202                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1203                 CHECKGLERROR
1204                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1205         }
1206         else
1207                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1208
1209         // free the strings
1210         if (vertexstring)
1211                 Mem_Free(vertexstring);
1212         if (geometrystring)
1213                 Mem_Free(geometrystring);
1214         if (fragmentstring)
1215                 Mem_Free(fragmentstring);
1216 }
1217
1218 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1219 {
1220         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1221         if (r_glsl_permutation != perm)
1222         {
1223                 r_glsl_permutation = perm;
1224                 if (!r_glsl_permutation->program)
1225                 {
1226                         if (!r_glsl_permutation->compiled)
1227                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1228                         if (!r_glsl_permutation->program)
1229                         {
1230                                 // remove features until we find a valid permutation
1231                                 int i;
1232                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1233                                 {
1234                                         // reduce i more quickly whenever it would not remove any bits
1235                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1236                                         if (!(permutation & j))
1237                                                 continue;
1238                                         permutation -= j;
1239                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1240                                         if (!r_glsl_permutation->compiled)
1241                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1242                                         if (r_glsl_permutation->program)
1243                                                 break;
1244                                 }
1245                                 if (i >= SHADERPERMUTATION_COUNT)
1246                                 {
1247                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1248                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1249                                         qglUseProgram(0);CHECKGLERROR
1250                                         return; // no bit left to clear, entire mode is broken
1251                                 }
1252                         }
1253                 }
1254                 CHECKGLERROR
1255                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1256         }
1257         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1258         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1259         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1260 }
1261
1262 #ifdef SUPPORTD3D
1263
1264 #ifdef SUPPORTD3D
1265 #include <d3d9.h>
1266 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1267 extern D3DCAPS9 vid_d3d9caps;
1268 #endif
1269
1270 struct r_hlsl_permutation_s;
1271 typedef struct r_hlsl_permutation_s
1272 {
1273         /// hash lookup data
1274         struct r_hlsl_permutation_s *hashnext;
1275         unsigned int mode;
1276         unsigned int permutation;
1277
1278         /// indicates if we have tried compiling this permutation already
1279         qboolean compiled;
1280         /// NULL if compilation failed
1281         IDirect3DVertexShader9 *vertexshader;
1282         IDirect3DPixelShader9 *pixelshader;
1283 }
1284 r_hlsl_permutation_t;
1285
1286 typedef enum D3DVSREGISTER_e
1287 {
1288         D3DVSREGISTER_TexMatrix = 0, // float4x4
1289         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1290         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1291         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1292         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1293         D3DVSREGISTER_ModelToLight = 20, // float4x4
1294         D3DVSREGISTER_EyePosition = 24,
1295         D3DVSREGISTER_FogPlane = 25,
1296         D3DVSREGISTER_LightDir = 26,
1297         D3DVSREGISTER_LightPosition = 27,
1298 }
1299 D3DVSREGISTER_t;
1300
1301 typedef enum D3DPSREGISTER_e
1302 {
1303         D3DPSREGISTER_Alpha = 0,
1304         D3DPSREGISTER_BloomBlur_Parameters = 1,
1305         D3DPSREGISTER_ClientTime = 2,
1306         D3DPSREGISTER_Color_Ambient = 3,
1307         D3DPSREGISTER_Color_Diffuse = 4,
1308         D3DPSREGISTER_Color_Specular = 5,
1309         D3DPSREGISTER_Color_Glow = 6,
1310         D3DPSREGISTER_Color_Pants = 7,
1311         D3DPSREGISTER_Color_Shirt = 8,
1312         D3DPSREGISTER_DeferredColor_Ambient = 9,
1313         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1314         D3DPSREGISTER_DeferredColor_Specular = 11,
1315         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1316         D3DPSREGISTER_DeferredMod_Specular = 13,
1317         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1318         D3DPSREGISTER_EyePosition = 15, // unused
1319         D3DPSREGISTER_FogColor = 16,
1320         D3DPSREGISTER_FogHeightFade = 17,
1321         D3DPSREGISTER_FogPlane = 18,
1322         D3DPSREGISTER_FogPlaneViewDist = 19,
1323         D3DPSREGISTER_FogRangeRecip = 20,
1324         D3DPSREGISTER_LightColor = 21,
1325         D3DPSREGISTER_LightDir = 22, // unused
1326         D3DPSREGISTER_LightPosition = 23,
1327         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1328         D3DPSREGISTER_PixelSize = 25,
1329         D3DPSREGISTER_ReflectColor = 26,
1330         D3DPSREGISTER_ReflectFactor = 27,
1331         D3DPSREGISTER_ReflectOffset = 28,
1332         D3DPSREGISTER_RefractColor = 29,
1333         D3DPSREGISTER_Saturation = 30,
1334         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1335         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1336         D3DPSREGISTER_ScreenToDepth = 33,
1337         D3DPSREGISTER_ShadowMap_Parameters = 34,
1338         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1339         D3DPSREGISTER_SpecularPower = 36,
1340         D3DPSREGISTER_UserVec1 = 37,
1341         D3DPSREGISTER_UserVec2 = 38,
1342         D3DPSREGISTER_UserVec3 = 39,
1343         D3DPSREGISTER_UserVec4 = 40,
1344         D3DPSREGISTER_ViewTintColor = 41,
1345         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1346         D3DPSREGISTER_BloomColorSubtract = 43,
1347         D3DPSREGISTER_ViewToLight = 44, // float4x4
1348         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1349         D3DPSREGISTER_NormalmapScrollBlend = 52,
1350         // next at 53
1351 }
1352 D3DPSREGISTER_t;
1353
1354 /// information about each possible shader permutation
1355 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1356 /// currently selected permutation
1357 r_hlsl_permutation_t *r_hlsl_permutation;
1358 /// storage for permutations linked in the hash table
1359 memexpandablearray_t r_hlsl_permutationarray;
1360
1361 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1362 {
1363         //unsigned int hashdepth = 0;
1364         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1365         r_hlsl_permutation_t *p;
1366         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1367         {
1368                 if (p->mode == mode && p->permutation == permutation)
1369                 {
1370                         //if (hashdepth > 10)
1371                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1372                         return p;
1373                 }
1374                 //hashdepth++;
1375         }
1376         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1377         p->mode = mode;
1378         p->permutation = permutation;
1379         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1380         r_hlsl_permutationhash[mode][hashindex] = p;
1381         //if (hashdepth > 10)
1382         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1383         return p;
1384 }
1385
1386 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1387 {
1388         char *shaderstring;
1389         if (!filename || !filename[0])
1390                 return NULL;
1391         if (!strcmp(filename, "hlsl/default.hlsl"))
1392         {
1393                 if (!hlslshaderstring)
1394                 {
1395                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1396                         if (hlslshaderstring)
1397                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1398                         else
1399                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1400                 }
1401                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1402                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1403                 return shaderstring;
1404         }
1405         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1406         if (shaderstring)
1407         {
1408                 if (printfromdisknotice)
1409                         Con_DPrintf("from disk %s... ", filename);
1410                 return shaderstring;
1411         }
1412         return shaderstring;
1413 }
1414
1415 #include <d3dx9.h>
1416 //#include <d3dx9shader.h>
1417 //#include <d3dx9mesh.h>
1418
1419 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1420 {
1421         DWORD *vsbin = NULL;
1422         DWORD *psbin = NULL;
1423         fs_offset_t vsbinsize;
1424         fs_offset_t psbinsize;
1425 //      IDirect3DVertexShader9 *vs = NULL;
1426 //      IDirect3DPixelShader9 *ps = NULL;
1427         ID3DXBuffer *vslog = NULL;
1428         ID3DXBuffer *vsbuffer = NULL;
1429         ID3DXConstantTable *vsconstanttable = NULL;
1430         ID3DXBuffer *pslog = NULL;
1431         ID3DXBuffer *psbuffer = NULL;
1432         ID3DXConstantTable *psconstanttable = NULL;
1433         int vsresult = 0;
1434         int psresult = 0;
1435         char temp[MAX_INPUTLINE];
1436         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1437         qboolean debugshader = gl_paranoid.integer != 0;
1438         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1439         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1440         if (!debugshader)
1441         {
1442                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1443                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1444         }
1445         if ((!vsbin && vertstring) || (!psbin && fragstring))
1446         {
1447                 const char* dllnames_d3dx9 [] =
1448                 {
1449                         "d3dx9_43.dll",
1450                         "d3dx9_42.dll",
1451                         "d3dx9_41.dll",
1452                         "d3dx9_40.dll",
1453                         "d3dx9_39.dll",
1454                         "d3dx9_38.dll",
1455                         "d3dx9_37.dll",
1456                         "d3dx9_36.dll",
1457                         "d3dx9_35.dll",
1458                         "d3dx9_34.dll",
1459                         "d3dx9_33.dll",
1460                         "d3dx9_32.dll",
1461                         "d3dx9_31.dll",
1462                         "d3dx9_30.dll",
1463                         "d3dx9_29.dll",
1464                         "d3dx9_28.dll",
1465                         "d3dx9_27.dll",
1466                         "d3dx9_26.dll",
1467                         "d3dx9_25.dll",
1468                         "d3dx9_24.dll",
1469                         NULL
1470                 };
1471                 dllhandle_t d3dx9_dll = NULL;
1472                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1473                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1474                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1475                 dllfunction_t d3dx9_dllfuncs[] =
1476                 {
1477                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1478                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1479                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1480                         {NULL, NULL}
1481                 };
1482                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1483                 {
1484                         DWORD shaderflags = 0;
1485                         if (debugshader)
1486                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1487                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1488                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1489                         if (vertstring && vertstring[0])
1490                         {
1491                                 if (debugshader)
1492                                 {
1493 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1494 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1495                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1496                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1497                                 }
1498                                 else
1499                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1500                                 if (vsbuffer)
1501                                 {
1502                                         vsbinsize = vsbuffer->GetBufferSize();
1503                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1504                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1505                                         vsbuffer->Release();
1506                                 }
1507                                 if (vslog)
1508                                 {
1509                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1510                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1511                                         vslog->Release();
1512                                 }
1513                         }
1514                         if (fragstring && fragstring[0])
1515                         {
1516                                 if (debugshader)
1517                                 {
1518 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1519 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1520                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1521                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1522                                 }
1523                                 else
1524                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1525                                 if (psbuffer)
1526                                 {
1527                                         psbinsize = psbuffer->GetBufferSize();
1528                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1529                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1530                                         psbuffer->Release();
1531                                 }
1532                                 if (pslog)
1533                                 {
1534                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1535                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1536                                         pslog->Release();
1537                                 }
1538                         }
1539                         Sys_UnloadLibrary(&d3dx9_dll);
1540                 }
1541                 else
1542                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1543         }
1544         if (vsbin && psbin)
1545         {
1546                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1547                 if (FAILED(vsresult))
1548                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1549                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1550                 if (FAILED(psresult))
1551                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1552         }
1553         // free the shader data
1554         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1555         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1556 }
1557
1558 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1559 {
1560         int i;
1561         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1562         int vertstring_length = 0;
1563         int geomstring_length = 0;
1564         int fragstring_length = 0;
1565         char *t;
1566         char *vertexstring, *geometrystring, *fragmentstring;
1567         char *vertstring, *geomstring, *fragstring;
1568         char permutationname[256];
1569         char cachename[256];
1570         int vertstrings_count = 0;
1571         int geomstrings_count = 0;
1572         int fragstrings_count = 0;
1573         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1574         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1575         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1576
1577         if (p->compiled)
1578                 return;
1579         p->compiled = true;
1580         p->vertexshader = NULL;
1581         p->pixelshader = NULL;
1582
1583         permutationname[0] = 0;
1584         cachename[0] = 0;
1585         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1586         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1587         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1588
1589         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1590         strlcat(cachename, "hlsl/", sizeof(cachename));
1591
1592         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1593         vertstrings_count = 0;
1594         geomstrings_count = 0;
1595         fragstrings_count = 0;
1596         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1597         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1598         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1599
1600         // the first pretext is which type of shader to compile as
1601         // (later these will all be bound together as a program object)
1602         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1603         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1604         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1605
1606         // the second pretext is the mode (for example a light source)
1607         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1608         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1609         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1610         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1611         strlcat(cachename, modeinfo->name, sizeof(cachename));
1612
1613         // now add all the permutation pretexts
1614         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1615         {
1616                 if (permutation & (1<<i))
1617                 {
1618                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1619                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1620                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1621                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1622                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1623                 }
1624                 else
1625                 {
1626                         // keep line numbers correct
1627                         vertstrings_list[vertstrings_count++] = "\n";
1628                         geomstrings_list[geomstrings_count++] = "\n";
1629                         fragstrings_list[fragstrings_count++] = "\n";
1630                 }
1631         }
1632
1633         // add static parms
1634         R_CompileShader_AddStaticParms(mode, permutation);
1635         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1636         vertstrings_count += shaderstaticparms_count;
1637         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1638         geomstrings_count += shaderstaticparms_count;
1639         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1640         fragstrings_count += shaderstaticparms_count;
1641
1642         // replace spaces in the cachename with _ characters
1643         for (i = 0;cachename[i];i++)
1644                 if (cachename[i] == ' ')
1645                         cachename[i] = '_';
1646
1647         // now append the shader text itself
1648         vertstrings_list[vertstrings_count++] = vertexstring;
1649         geomstrings_list[geomstrings_count++] = geometrystring;
1650         fragstrings_list[fragstrings_count++] = fragmentstring;
1651
1652         // if any sources were NULL, clear the respective list
1653         if (!vertexstring)
1654                 vertstrings_count = 0;
1655         if (!geometrystring)
1656                 geomstrings_count = 0;
1657         if (!fragmentstring)
1658                 fragstrings_count = 0;
1659
1660         vertstring_length = 0;
1661         for (i = 0;i < vertstrings_count;i++)
1662                 vertstring_length += strlen(vertstrings_list[i]);
1663         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1664         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1665                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1666
1667         geomstring_length = 0;
1668         for (i = 0;i < geomstrings_count;i++)
1669                 geomstring_length += strlen(geomstrings_list[i]);
1670         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1671         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1672                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1673
1674         fragstring_length = 0;
1675         for (i = 0;i < fragstrings_count;i++)
1676                 fragstring_length += strlen(fragstrings_list[i]);
1677         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1678         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1679                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1680
1681         // try to load the cached shader, or generate one
1682         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1683
1684         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1685                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1686         else
1687                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1688
1689         // free the strings
1690         if (vertstring)
1691                 Mem_Free(vertstring);
1692         if (geomstring)
1693                 Mem_Free(geomstring);
1694         if (fragstring)
1695                 Mem_Free(fragstring);
1696         if (vertexstring)
1697                 Mem_Free(vertexstring);
1698         if (geometrystring)
1699                 Mem_Free(geometrystring);
1700         if (fragmentstring)
1701                 Mem_Free(fragmentstring);
1702 }
1703
1704 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1705 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1706 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);}
1707 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);}
1708 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);}
1709 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);}
1710
1711 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1712 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1713 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);}
1714 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);}
1715 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);}
1716 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);}
1717
1718 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1719 {
1720         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1721         if (r_hlsl_permutation != perm)
1722         {
1723                 r_hlsl_permutation = perm;
1724                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1725                 {
1726                         if (!r_hlsl_permutation->compiled)
1727                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1728                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1729                         {
1730                                 // remove features until we find a valid permutation
1731                                 int i;
1732                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1733                                 {
1734                                         // reduce i more quickly whenever it would not remove any bits
1735                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1736                                         if (!(permutation & j))
1737                                                 continue;
1738                                         permutation -= j;
1739                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1740                                         if (!r_hlsl_permutation->compiled)
1741                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1742                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1743                                                 break;
1744                                 }
1745                                 if (i >= SHADERPERMUTATION_COUNT)
1746                                 {
1747                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1748                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1749                                         return; // no bit left to clear, entire mode is broken
1750                                 }
1751                         }
1752                 }
1753                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1754                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1755         }
1756         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1757         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1758         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1759 }
1760 #endif
1761
1762 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1763 {
1764         DPSOFTRAST_SetShader(mode, permutation);
1765         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1766         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1767         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1768 }
1769
1770 void R_GLSL_Restart_f(void)
1771 {
1772         unsigned int i, limit;
1773         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1774                 Mem_Free(glslshaderstring);
1775         glslshaderstring = NULL;
1776         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1777                 Mem_Free(hlslshaderstring);
1778         hlslshaderstring = NULL;
1779         switch(vid.renderpath)
1780         {
1781         case RENDERPATH_D3D9:
1782 #ifdef SUPPORTD3D
1783                 {
1784                         r_hlsl_permutation_t *p;
1785                         r_hlsl_permutation = NULL;
1786                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1787                         for (i = 0;i < limit;i++)
1788                         {
1789                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1790                                 {
1791                                         if (p->vertexshader)
1792                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1793                                         if (p->pixelshader)
1794                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1795                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1796                                 }
1797                         }
1798                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1799                 }
1800 #endif
1801                 break;
1802         case RENDERPATH_D3D10:
1803                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1804                 break;
1805         case RENDERPATH_D3D11:
1806                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1807                 break;
1808         case RENDERPATH_GL20:
1809         case RENDERPATH_GLES2:
1810                 {
1811                         r_glsl_permutation_t *p;
1812                         r_glsl_permutation = NULL;
1813                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1814                         for (i = 0;i < limit;i++)
1815                         {
1816                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1817                                 {
1818                                         GL_Backend_FreeProgram(p->program);
1819                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1820                                 }
1821                         }
1822                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1823                 }
1824                 break;
1825         case RENDERPATH_GL13:
1826         case RENDERPATH_GL11:
1827                 break;
1828         case RENDERPATH_SOFT:
1829                 break;
1830         }
1831 }
1832
1833 void R_GLSL_DumpShader_f(void)
1834 {
1835         int i;
1836         qfile_t *file;
1837
1838         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1839         if (file)
1840         {
1841                 FS_Print(file, "/* The engine may define the following macros:\n");
1842                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1843                 for (i = 0;i < SHADERMODE_COUNT;i++)
1844                         FS_Print(file, glslshadermodeinfo[i].pretext);
1845                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1846                         FS_Print(file, shaderpermutationinfo[i].pretext);
1847                 FS_Print(file, "*/\n");
1848                 FS_Print(file, builtinshaderstring);
1849                 FS_Close(file);
1850                 Con_Printf("glsl/default.glsl written\n");
1851         }
1852         else
1853                 Con_Printf("failed to write to glsl/default.glsl\n");
1854
1855         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1856         if (file)
1857         {
1858                 FS_Print(file, "/* The engine may define the following macros:\n");
1859                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1860                 for (i = 0;i < SHADERMODE_COUNT;i++)
1861                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1862                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1863                         FS_Print(file, shaderpermutationinfo[i].pretext);
1864                 FS_Print(file, "*/\n");
1865                 FS_Print(file, builtinhlslshaderstring);
1866                 FS_Close(file);
1867                 Con_Printf("hlsl/default.hlsl written\n");
1868         }
1869         else
1870                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1871 }
1872
1873 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1874 {
1875         if (!second)
1876                 texturemode = GL_MODULATE;
1877         switch (vid.renderpath)
1878         {
1879         case RENDERPATH_D3D9:
1880 #ifdef SUPPORTD3D
1881                 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))));
1882                 R_Mesh_TexBind(GL20TU_FIRST , first );
1883                 R_Mesh_TexBind(GL20TU_SECOND, second);
1884 #endif
1885                 break;
1886         case RENDERPATH_D3D10:
1887                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1888                 break;
1889         case RENDERPATH_D3D11:
1890                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1891                 break;
1892         case RENDERPATH_GL20:
1893         case RENDERPATH_GLES2:
1894                 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))));
1895                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1896                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1897                 break;
1898         case RENDERPATH_GL13:
1899                 R_Mesh_TexBind(0, first );
1900                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1901                 R_Mesh_TexBind(1, second);
1902                 if (second)
1903                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1904                 break;
1905         case RENDERPATH_GL11:
1906                 R_Mesh_TexBind(0, first );
1907                 break;
1908         case RENDERPATH_SOFT:
1909                 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))));
1910                 R_Mesh_TexBind(GL20TU_FIRST , first );
1911                 R_Mesh_TexBind(GL20TU_SECOND, second);
1912                 break;
1913         }
1914 }
1915
1916 void R_SetupShader_DepthOrShadow(void)
1917 {
1918         switch (vid.renderpath)
1919         {
1920         case RENDERPATH_D3D9:
1921 #ifdef SUPPORTD3D
1922                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1923 #endif
1924                 break;
1925         case RENDERPATH_D3D10:
1926                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1927                 break;
1928         case RENDERPATH_D3D11:
1929                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1930                 break;
1931         case RENDERPATH_GL20:
1932         case RENDERPATH_GLES2:
1933                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1934                 break;
1935         case RENDERPATH_GL13:
1936                 R_Mesh_TexBind(0, 0);
1937                 R_Mesh_TexBind(1, 0);
1938                 break;
1939         case RENDERPATH_GL11:
1940                 R_Mesh_TexBind(0, 0);
1941                 break;
1942         case RENDERPATH_SOFT:
1943                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1944                 break;
1945         }
1946 }
1947
1948 void R_SetupShader_ShowDepth(void)
1949 {
1950         switch (vid.renderpath)
1951         {
1952         case RENDERPATH_D3D9:
1953 #ifdef SUPPORTHLSL
1954                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1955 #endif
1956                 break;
1957         case RENDERPATH_D3D10:
1958                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1959                 break;
1960         case RENDERPATH_D3D11:
1961                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1962                 break;
1963         case RENDERPATH_GL20:
1964         case RENDERPATH_GLES2:
1965                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1966                 break;
1967         case RENDERPATH_GL13:
1968                 break;
1969         case RENDERPATH_GL11:
1970                 break;
1971         case RENDERPATH_SOFT:
1972                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1973                 break;
1974         }
1975 }
1976
1977 extern qboolean r_shadow_usingdeferredprepass;
1978 extern cvar_t r_shadow_deferred_8bitrange;
1979 extern rtexture_t *r_shadow_attenuationgradienttexture;
1980 extern rtexture_t *r_shadow_attenuation2dtexture;
1981 extern rtexture_t *r_shadow_attenuation3dtexture;
1982 extern qboolean r_shadow_usingshadowmap2d;
1983 extern qboolean r_shadow_usingshadowmaportho;
1984 extern float r_shadow_shadowmap_texturescale[2];
1985 extern float r_shadow_shadowmap_parameters[4];
1986 extern qboolean r_shadow_shadowmapvsdct;
1987 extern qboolean r_shadow_shadowmapsampler;
1988 extern int r_shadow_shadowmappcf;
1989 extern rtexture_t *r_shadow_shadowmap2dtexture;
1990 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1991 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1992 extern matrix4x4_t r_shadow_shadowmapmatrix;
1993 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1994 extern int r_shadow_prepass_width;
1995 extern int r_shadow_prepass_height;
1996 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1997 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1998 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
1999 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2000 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2001
2002 #define BLENDFUNC_ALLOWS_COLORMOD      1
2003 #define BLENDFUNC_ALLOWS_FOG           2
2004 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2005 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2006 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2007 static int R_BlendFuncFlags(int src, int dst)
2008 {
2009         int r = 0;
2010
2011         // a blendfunc allows colormod if:
2012         // a) it can never keep the destination pixel invariant, or
2013         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2014         // this is to prevent unintended side effects from colormod
2015
2016         // a blendfunc allows fog if:
2017         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2018         // this is to prevent unintended side effects from fog
2019
2020         // these checks are the output of fogeval.pl
2021
2022         r |= BLENDFUNC_ALLOWS_COLORMOD;
2023         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2024         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2025         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2026         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2027         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2028         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2029         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2030         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2031         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2032         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2033         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2034         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2035         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2036         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2037         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2038         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2039         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2040         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2041         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2042         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2043         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2044
2045         return r;
2046 }
2047
2048 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)
2049 {
2050         // select a permutation of the lighting shader appropriate to this
2051         // combination of texture, entity, light source, and fogging, only use the
2052         // minimum features necessary to avoid wasting rendering time in the
2053         // fragment shader on features that are not being used
2054         unsigned int permutation = 0;
2055         unsigned int mode = 0;
2056         int blendfuncflags;
2057         static float dummy_colormod[3] = {1, 1, 1};
2058         float *colormod = rsurface.colormod;
2059         float m16f[16];
2060         matrix4x4_t tempmatrix;
2061         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2062         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2063                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2064         if (rsurfacepass == RSURFPASS_BACKGROUND)
2065         {
2066                 // distorted background
2067                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2068                 {
2069                         mode = SHADERMODE_WATER;
2070                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2071                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2072                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2073                         {
2074                                 // this is the right thing to do for wateralpha
2075                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2076                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2077                         }
2078                         else
2079                         {
2080                                 // this is the right thing to do for entity alpha
2081                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2082                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2083                         }
2084                 }
2085                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2086                 {
2087                         mode = SHADERMODE_REFRACTION;
2088                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2089                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2090                 }
2091                 else
2092                 {
2093                         mode = SHADERMODE_GENERIC;
2094                         permutation |= SHADERPERMUTATION_DIFFUSE;
2095                         GL_BlendFunc(GL_ONE, GL_ZERO);
2096                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2097                 }
2098         }
2099         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2100         {
2101                 if (r_glsl_offsetmapping.integer)
2102                 {
2103                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2104                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2105                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2106                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2107                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2108                         {
2109                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2110                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2111                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2112                         }
2113                 }
2114                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2115                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2116                 // normalmap (deferred prepass), may use alpha test on diffuse
2117                 mode = SHADERMODE_DEFERREDGEOMETRY;
2118                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2119                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2120                 GL_BlendFunc(GL_ONE, GL_ZERO);
2121                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2122         }
2123         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2124         {
2125                 if (r_glsl_offsetmapping.integer)
2126                 {
2127                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2128                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2129                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2130                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2131                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2132                         {
2133                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2134                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2135                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2136                         }
2137                 }
2138                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2139                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2140                 // light source
2141                 mode = SHADERMODE_LIGHTSOURCE;
2142                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2143                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2144                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2145                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2146                 if (diffusescale > 0)
2147                         permutation |= SHADERPERMUTATION_DIFFUSE;
2148                 if (specularscale > 0)
2149                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2150                 if (r_refdef.fogenabled)
2151                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2152                 if (rsurface.texture->colormapping)
2153                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2154                 if (r_shadow_usingshadowmap2d)
2155                 {
2156                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2157                         if(r_shadow_shadowmapvsdct)
2158                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2159
2160                         if (r_shadow_shadowmapsampler)
2161                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2162                         if (r_shadow_shadowmappcf > 1)
2163                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2164                         else if (r_shadow_shadowmappcf)
2165                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2166                 }
2167                 if (rsurface.texture->reflectmasktexture)
2168                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2169                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2170                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2171         }
2172         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2173         {
2174                 if (r_glsl_offsetmapping.integer)
2175                 {
2176                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2177                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2178                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2179                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2180                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2181                         {
2182                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2183                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2184                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2185                         }
2186                 }
2187                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2188                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2189                 // unshaded geometry (fullbright or ambient model lighting)
2190                 mode = SHADERMODE_FLATCOLOR;
2191                 ambientscale = diffusescale = specularscale = 0;
2192                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2193                         permutation |= SHADERPERMUTATION_GLOW;
2194                 if (r_refdef.fogenabled)
2195                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2196                 if (rsurface.texture->colormapping)
2197                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2198                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2199                 {
2200                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2201                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2202
2203                         if (r_shadow_shadowmapsampler)
2204                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2205                         if (r_shadow_shadowmappcf > 1)
2206                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2207                         else if (r_shadow_shadowmappcf)
2208                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2209                 }
2210                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2211                         permutation |= SHADERPERMUTATION_REFLECTION;
2212                 if (rsurface.texture->reflectmasktexture)
2213                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2214                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2215                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2216         }
2217         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2218         {
2219                 if (r_glsl_offsetmapping.integer)
2220                 {
2221                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2222                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2223                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2224                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2225                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2226                         {
2227                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2228                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2229                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2230                         }
2231                 }
2232                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2233                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2234                 // directional model lighting
2235                 mode = SHADERMODE_LIGHTDIRECTION;
2236                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2237                         permutation |= SHADERPERMUTATION_GLOW;
2238                 permutation |= SHADERPERMUTATION_DIFFUSE;
2239                 if (specularscale > 0)
2240                         permutation |= SHADERPERMUTATION_SPECULAR;
2241                 if (r_refdef.fogenabled)
2242                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2243                 if (rsurface.texture->colormapping)
2244                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2245                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2246                 {
2247                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2248                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2249
2250                         if (r_shadow_shadowmapsampler)
2251                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2252                         if (r_shadow_shadowmappcf > 1)
2253                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2254                         else if (r_shadow_shadowmappcf)
2255                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2256                 }
2257                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2258                         permutation |= SHADERPERMUTATION_REFLECTION;
2259                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2260                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2261                 if (rsurface.texture->reflectmasktexture)
2262                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2263                 if (r_shadow_bouncegridtexture)
2264                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2265                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2266                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2267         }
2268         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2269         {
2270                 if (r_glsl_offsetmapping.integer)
2271                 {
2272                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2273                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2274                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2275                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2276                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2277                         {
2278                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2279                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2280                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2281                         }
2282                 }
2283                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2284                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2285                 // ambient model lighting
2286                 mode = SHADERMODE_LIGHTDIRECTION;
2287                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2288                         permutation |= SHADERPERMUTATION_GLOW;
2289                 if (r_refdef.fogenabled)
2290                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2291                 if (rsurface.texture->colormapping)
2292                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2293                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2294                 {
2295                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2296                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2297
2298                         if (r_shadow_shadowmapsampler)
2299                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2300                         if (r_shadow_shadowmappcf > 1)
2301                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2302                         else if (r_shadow_shadowmappcf)
2303                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2304                 }
2305                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2306                         permutation |= SHADERPERMUTATION_REFLECTION;
2307                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2308                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2309                 if (rsurface.texture->reflectmasktexture)
2310                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2311                 if (r_shadow_bouncegridtexture)
2312                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2313                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2314                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2315         }
2316         else
2317         {
2318                 if (r_glsl_offsetmapping.integer)
2319                 {
2320                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2321                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2322                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2323                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2324                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2325                         {
2326                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2327                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2328                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2329                         }
2330                 }
2331                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2332                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2333                 // lightmapped wall
2334                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2335                         permutation |= SHADERPERMUTATION_GLOW;
2336                 if (r_refdef.fogenabled)
2337                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2338                 if (rsurface.texture->colormapping)
2339                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2340                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2341                 {
2342                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2343                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2344
2345                         if (r_shadow_shadowmapsampler)
2346                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2347                         if (r_shadow_shadowmappcf > 1)
2348                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2349                         else if (r_shadow_shadowmappcf)
2350                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2351                 }
2352                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2353                         permutation |= SHADERPERMUTATION_REFLECTION;
2354                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2355                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2356                 if (rsurface.texture->reflectmasktexture)
2357                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2358                 if (FAKELIGHT_ENABLED)
2359                 {
2360                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2361                         mode = SHADERMODE_FAKELIGHT;
2362                         permutation |= SHADERPERMUTATION_DIFFUSE;
2363                         if (specularscale > 0)
2364                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2365                 }
2366                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2367                 {
2368                         // deluxemapping (light direction texture)
2369                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2370                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2371                         else
2372                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2373                         permutation |= SHADERPERMUTATION_DIFFUSE;
2374                         if (specularscale > 0)
2375                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2376                 }
2377                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2378                 {
2379                         // fake deluxemapping (uniform light direction in tangentspace)
2380                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2381                         permutation |= SHADERPERMUTATION_DIFFUSE;
2382                         if (specularscale > 0)
2383                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2384                 }
2385                 else if (rsurface.uselightmaptexture)
2386                 {
2387                         // ordinary lightmapping (q1bsp, q3bsp)
2388                         mode = SHADERMODE_LIGHTMAP;
2389                 }
2390                 else
2391                 {
2392                         // ordinary vertex coloring (q3bsp)
2393                         mode = SHADERMODE_VERTEXCOLOR;
2394                 }
2395                 if (r_shadow_bouncegridtexture)
2396                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2397                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2398                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2399         }
2400         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2401                 colormod = dummy_colormod;
2402         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2403                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2404         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2405                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2406         switch(vid.renderpath)
2407         {
2408         case RENDERPATH_D3D9:
2409 #ifdef SUPPORTD3D
2410                 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);
2411                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2412                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2413                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2414                 if (mode == SHADERMODE_LIGHTSOURCE)
2415                 {
2416                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2417                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2418                 }
2419                 else
2420                 {
2421                         if (mode == SHADERMODE_LIGHTDIRECTION)
2422                         {
2423                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2424                         }
2425                 }
2426                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2427                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2428                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2429                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2430                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2431
2432                 if (mode == SHADERMODE_LIGHTSOURCE)
2433                 {
2434                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2435                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2436                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2437                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2438                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2439
2440                         // additive passes are only darkened by fog, not tinted
2441                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2442                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2443                 }
2444                 else
2445                 {
2446                         if (mode == SHADERMODE_FLATCOLOR)
2447                         {
2448                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2449                         }
2450                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2451                         {
2452                                 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]);
2453                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2454                                 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);
2455                                 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);
2456                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2457                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2458                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2459                         }
2460                         else
2461                         {
2462                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2463                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2464                                 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);
2465                                 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);
2466                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2467                         }
2468                         // additive passes are only darkened by fog, not tinted
2469                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2470                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2471                         else
2472                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2473                         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);
2474                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2475                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2476                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2477                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2478                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2479                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2480                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2481                         if (mode == SHADERMODE_WATER)
2482                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2483                 }
2484                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2485                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2486                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2487                 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));
2488                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2489                 if (rsurface.texture->pantstexture)
2490                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2491                 else
2492                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2493                 if (rsurface.texture->shirttexture)
2494                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2495                 else
2496                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2497                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2498                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2499                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2500                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2501                 hlslPSSetParameter3f(D3DPSREGISTER_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2502                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2503                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2504
2505                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2506                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2507                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2508                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2509                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2510                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2511                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2512                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2513                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2514                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2515                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2516                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2517                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2518                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2519                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2520                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2521                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2522                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2523                 {
2524                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2525                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2526                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2527                 }
2528                 else
2529                 {
2530                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2531                 }
2532 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2533 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2534                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2535                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2536                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2537                 {
2538                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2539                         if (rsurface.rtlight)
2540                         {
2541                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2542                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2543                         }
2544                 }
2545 #endif
2546                 break;
2547         case RENDERPATH_D3D10:
2548                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2549                 break;
2550         case RENDERPATH_D3D11:
2551                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2552                 break;
2553         case RENDERPATH_GL20:
2554         case RENDERPATH_GLES2:
2555                 if (!vid.useinterleavedarrays)
2556                 {
2557                         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);
2558                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2559                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2560                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2561                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2562                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2563                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2564                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2565                 }
2566                 else
2567                 {
2568                         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);
2569                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2570                 }
2571                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2572                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2573                 if (mode == SHADERMODE_LIGHTSOURCE)
2574                 {
2575                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2576                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2577                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2578                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2579                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2580                         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);
2581         
2582                         // additive passes are only darkened by fog, not tinted
2583                         if (r_glsl_permutation->loc_FogColor >= 0)
2584                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2585                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2586                 }
2587                 else
2588                 {
2589                         if (mode == SHADERMODE_FLATCOLOR)
2590                         {
2591                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2592                         }
2593                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2594                         {
2595                                 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]);
2596                                 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]);
2597                                 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);
2598                                 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);
2599                                 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);
2600                                 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]);
2601                                 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]);
2602                         }
2603                         else
2604                         {
2605                                 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]);
2606                                 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]);
2607                                 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);
2608                                 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);
2609                                 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);
2610                         }
2611                         // additive passes are only darkened by fog, not tinted
2612                         if (r_glsl_permutation->loc_FogColor >= 0)
2613                         {
2614                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2615                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2616                                 else
2617                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2618                         }
2619                         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);
2620                         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]);
2621                         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]);
2622                         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]);
2623                         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]);
2624                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2625                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2626                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2627                         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]);
2628                 }
2629                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2630                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2631                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2632                 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]);
2633                 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]);
2634
2635                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2636                 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));
2637                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2638                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2639                 {
2640                         if (rsurface.texture->pantstexture)
2641                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2642                         else
2643                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2644                 }
2645                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2646                 {
2647                         if (rsurface.texture->shirttexture)
2648                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2649                         else
2650                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2651                 }
2652                 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]);
2653                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2654                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2655                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2656                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform3f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2657                 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]);
2658                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2659                 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);}
2660                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2661
2662                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2663                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2664                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2665                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2666                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2667                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2668                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2669                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2670                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2671                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2672                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2673                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2674                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2675                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2676                 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);
2677                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2678                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2679                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2680                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2681                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2682                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2683                 {
2684                         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);
2685                         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);
2686                         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);
2687                 }
2688                 else
2689                 {
2690                         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);
2691                 }
2692                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2693                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2694                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2695                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2696                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2697                 {
2698                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2699                         if (rsurface.rtlight)
2700                         {
2701                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2702                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2703                         }
2704                 }
2705                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2706                 CHECKGLERROR
2707                 break;
2708         case RENDERPATH_GL13:
2709         case RENDERPATH_GL11:
2710                 break;
2711         case RENDERPATH_SOFT:
2712                 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);
2713                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2714                 R_SetupShader_SetPermutationSoft(mode, permutation);
2715                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2716                 if (mode == SHADERMODE_LIGHTSOURCE)
2717                 {
2718                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2719                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2720                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2721                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2722                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2723                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2724         
2725                         // additive passes are only darkened by fog, not tinted
2726                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2727                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2728                 }
2729                 else
2730                 {
2731                         if (mode == SHADERMODE_FLATCOLOR)
2732                         {
2733                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2734                         }
2735                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2736                         {
2737                                 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]);
2738                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2739                                 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);
2740                                 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);
2741                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2742                                 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]);
2743                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2744                         }
2745                         else
2746                         {
2747                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2748                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2749                                 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);
2750                                 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);
2751                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2752                         }
2753                         // additive passes are only darkened by fog, not tinted
2754                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2755                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2756                         else
2757                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2758                         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);
2759                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2760                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2761                         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]);
2762                         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]);
2763                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2764                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2765                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2766                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2767                 }
2768                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2769                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2770                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2771                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2772                 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]);
2773
2774                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2775                 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));
2776                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2777                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2778                 {
2779                         if (rsurface.texture->pantstexture)
2780                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2781                         else
2782                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2783                 }
2784                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2785                 {
2786                         if (rsurface.texture->shirttexture)
2787                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2788                         else
2789                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2790                 }
2791                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2792                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2793                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2794                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2795                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2796                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2797                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2798
2799                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2800                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2801                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2802                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2803                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2804                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2805                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2806                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2807                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2808                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2809                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2810                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2811                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2812                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2813                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2814                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2815                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2816                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2817                 {
2818                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2819                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2820                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2821                 }
2822                 else
2823                 {
2824                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2825                 }
2826 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2827 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2828                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2829                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2830                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2831                 {
2832                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2833                         if (rsurface.rtlight)
2834                         {
2835                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2836                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2837                         }
2838                 }
2839                 break;
2840         }
2841 }
2842
2843 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2844 {
2845         // select a permutation of the lighting shader appropriate to this
2846         // combination of texture, entity, light source, and fogging, only use the
2847         // minimum features necessary to avoid wasting rendering time in the
2848         // fragment shader on features that are not being used
2849         unsigned int permutation = 0;
2850         unsigned int mode = 0;
2851         const float *lightcolorbase = rtlight->currentcolor;
2852         float ambientscale = rtlight->ambientscale;
2853         float diffusescale = rtlight->diffusescale;
2854         float specularscale = rtlight->specularscale;
2855         // this is the location of the light in view space
2856         vec3_t viewlightorigin;
2857         // this transforms from view space (camera) to light space (cubemap)
2858         matrix4x4_t viewtolight;
2859         matrix4x4_t lighttoview;
2860         float viewtolight16f[16];
2861         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2862         // light source
2863         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2864         if (rtlight->currentcubemap != r_texture_whitecube)
2865                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2866         if (diffusescale > 0)
2867                 permutation |= SHADERPERMUTATION_DIFFUSE;
2868         if (specularscale > 0)
2869                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2870         if (r_shadow_usingshadowmap2d)
2871         {
2872                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2873                 if (r_shadow_shadowmapvsdct)
2874                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2875
2876                 if (r_shadow_shadowmapsampler)
2877                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2878                 if (r_shadow_shadowmappcf > 1)
2879                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2880                 else if (r_shadow_shadowmappcf)
2881                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2882         }
2883         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2884         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2885         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2886         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2887         switch(vid.renderpath)
2888         {
2889         case RENDERPATH_D3D9:
2890 #ifdef SUPPORTD3D
2891                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2892                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2893                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2894                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2895                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2896                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2897                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2898                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2899                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2900                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2901                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2902
2903                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2904                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2905                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2906                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2907                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2908                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2909 #endif
2910                 break;
2911         case RENDERPATH_D3D10:
2912                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2913                 break;
2914         case RENDERPATH_D3D11:
2915                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2916                 break;
2917         case RENDERPATH_GL20:
2918         case RENDERPATH_GLES2:
2919                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2920                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2921                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2922                 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);
2923                 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);
2924                 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);
2925                 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]);
2926                 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]);
2927                 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));
2928                 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]);
2929                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2930
2931                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2932                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2933                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2934                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2935                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2936                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2937                 break;
2938         case RENDERPATH_GL13:
2939         case RENDERPATH_GL11:
2940                 break;
2941         case RENDERPATH_SOFT:
2942                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2943                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2944                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2945                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2946                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2947                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2948                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2949                 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]);
2950                 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));
2951                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2952                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2953
2954                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2955                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2956                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2957                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2958                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2959                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2960                 break;
2961         }
2962 }
2963
2964 #define SKINFRAME_HASH 1024
2965
2966 typedef struct
2967 {
2968         int loadsequence; // incremented each level change
2969         memexpandablearray_t array;
2970         skinframe_t *hash[SKINFRAME_HASH];
2971 }
2972 r_skinframe_t;
2973 r_skinframe_t r_skinframe;
2974
2975 void R_SkinFrame_PrepareForPurge(void)
2976 {
2977         r_skinframe.loadsequence++;
2978         // wrap it without hitting zero
2979         if (r_skinframe.loadsequence >= 200)
2980                 r_skinframe.loadsequence = 1;
2981 }
2982
2983 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2984 {
2985         if (!skinframe)
2986                 return;
2987         // mark the skinframe as used for the purging code
2988         skinframe->loadsequence = r_skinframe.loadsequence;
2989 }
2990
2991 void R_SkinFrame_Purge(void)
2992 {
2993         int i;
2994         skinframe_t *s;
2995         for (i = 0;i < SKINFRAME_HASH;i++)
2996         {
2997                 for (s = r_skinframe.hash[i];s;s = s->next)
2998                 {
2999                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3000                         {
3001                                 if (s->merged == s->base)
3002                                         s->merged = NULL;
3003                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3004                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3005                                 R_PurgeTexture(s->merged);s->merged = NULL;
3006                                 R_PurgeTexture(s->base  );s->base   = NULL;
3007                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3008                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3009                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3010                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3011                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3012                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3013                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3014                                 s->loadsequence = 0;
3015                         }
3016                 }
3017         }
3018 }
3019
3020 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3021         skinframe_t *item;
3022         char basename[MAX_QPATH];
3023
3024         Image_StripImageExtension(name, basename, sizeof(basename));
3025
3026         if( last == NULL ) {
3027                 int hashindex;
3028                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3029                 item = r_skinframe.hash[hashindex];
3030         } else {
3031                 item = last->next;
3032         }
3033
3034         // linearly search through the hash bucket
3035         for( ; item ; item = item->next ) {
3036                 if( !strcmp( item->basename, basename ) ) {
3037                         return item;
3038                 }
3039         }
3040         return NULL;
3041 }
3042
3043 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3044 {
3045         skinframe_t *item;
3046         int hashindex;
3047         char basename[MAX_QPATH];
3048
3049         Image_StripImageExtension(name, basename, sizeof(basename));
3050
3051         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3052         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3053                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3054                         break;
3055
3056         if (!item) {
3057                 rtexture_t *dyntexture;
3058                 // check whether its a dynamic texture
3059                 dyntexture = CL_GetDynTexture( basename );
3060                 if (!add && !dyntexture)
3061                         return NULL;
3062                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3063                 memset(item, 0, sizeof(*item));
3064                 strlcpy(item->basename, basename, sizeof(item->basename));
3065                 item->base = dyntexture; // either NULL or dyntexture handle
3066                 item->textureflags = textureflags;
3067                 item->comparewidth = comparewidth;
3068                 item->compareheight = compareheight;
3069                 item->comparecrc = comparecrc;
3070                 item->next = r_skinframe.hash[hashindex];
3071                 r_skinframe.hash[hashindex] = item;
3072         }
3073         else if( item->base == NULL )
3074         {
3075                 rtexture_t *dyntexture;
3076                 // check whether its a dynamic texture
3077                 // 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]
3078                 dyntexture = CL_GetDynTexture( basename );
3079                 item->base = dyntexture; // either NULL or dyntexture handle
3080         }
3081
3082         R_SkinFrame_MarkUsed(item);
3083         return item;
3084 }
3085
3086 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3087         { \
3088                 unsigned long long avgcolor[5], wsum; \
3089                 int pix, comp, w; \
3090                 avgcolor[0] = 0; \
3091                 avgcolor[1] = 0; \
3092                 avgcolor[2] = 0; \
3093                 avgcolor[3] = 0; \
3094                 avgcolor[4] = 0; \
3095                 wsum = 0; \
3096                 for(pix = 0; pix < cnt; ++pix) \
3097                 { \
3098                         w = 0; \
3099                         for(comp = 0; comp < 3; ++comp) \
3100                                 w += getpixel; \
3101                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3102                         { \
3103                                 ++wsum; \
3104                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3105                                 w = getpixel; \
3106                                 for(comp = 0; comp < 3; ++comp) \
3107                                         avgcolor[comp] += getpixel * w; \
3108                                 avgcolor[3] += w; \
3109                         } \
3110                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3111                         avgcolor[4] += getpixel; \
3112                 } \
3113                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3114                         avgcolor[3] = 1; \
3115                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3116                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3117                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3118                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3119         }
3120
3121 extern cvar_t gl_picmip;
3122 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3123 {
3124         int j;
3125         unsigned char *pixels;
3126         unsigned char *bumppixels;
3127         unsigned char *basepixels = NULL;
3128         int basepixels_width = 0;
3129         int basepixels_height = 0;
3130         skinframe_t *skinframe;
3131         rtexture_t *ddsbase = NULL;
3132         qboolean ddshasalpha = false;
3133         float ddsavgcolor[4];
3134         char basename[MAX_QPATH];
3135         int miplevel = R_PicmipForFlags(textureflags);
3136         int savemiplevel = miplevel;
3137         int mymiplevel;
3138
3139         if (cls.state == ca_dedicated)
3140                 return NULL;
3141
3142         // return an existing skinframe if already loaded
3143         // if loading of the first image fails, don't make a new skinframe as it
3144         // would cause all future lookups of this to be missing
3145         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3146         if (skinframe && skinframe->base)
3147                 return skinframe;
3148
3149         Image_StripImageExtension(name, basename, sizeof(basename));
3150
3151         // check for DDS texture file first
3152         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3153         {
3154                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3155                 if (basepixels == NULL)
3156                         return NULL;
3157         }
3158
3159         // FIXME handle miplevel
3160
3161         if (developer_loading.integer)
3162                 Con_Printf("loading skin \"%s\"\n", name);
3163
3164         // we've got some pixels to store, so really allocate this new texture now
3165         if (!skinframe)
3166                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3167         skinframe->stain = NULL;
3168         skinframe->merged = NULL;
3169         skinframe->base = NULL;
3170         skinframe->pants = NULL;
3171         skinframe->shirt = NULL;
3172         skinframe->nmap = NULL;
3173         skinframe->gloss = NULL;
3174         skinframe->glow = NULL;
3175         skinframe->fog = NULL;
3176         skinframe->reflect = NULL;
3177         skinframe->hasalpha = false;
3178
3179         if (ddsbase)
3180         {
3181                 skinframe->base = ddsbase;
3182                 skinframe->hasalpha = ddshasalpha;
3183                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3184                 if (r_loadfog && skinframe->hasalpha)
3185                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3186                 //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]);
3187         }
3188         else
3189         {
3190                 basepixels_width = image_width;
3191                 basepixels_height = image_height;
3192                 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);
3193                 if (textureflags & TEXF_ALPHA)
3194                 {
3195                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3196                         {
3197                                 if (basepixels[j] < 255)
3198                                 {
3199                                         skinframe->hasalpha = true;
3200                                         break;
3201                                 }
3202                         }
3203                         if (r_loadfog && skinframe->hasalpha)
3204                         {
3205                                 // has transparent pixels
3206                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3207                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3208                                 {
3209                                         pixels[j+0] = 255;
3210                                         pixels[j+1] = 255;
3211                                         pixels[j+2] = 255;
3212                                         pixels[j+3] = basepixels[j+3];
3213                                 }
3214                                 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);
3215                                 Mem_Free(pixels);
3216                         }
3217                 }
3218                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3219                 //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]);
3220                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3221                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3222                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3223                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3224         }
3225
3226         if (r_loaddds)
3227         {
3228                 mymiplevel = savemiplevel;
3229                 if (r_loadnormalmap)
3230                         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);
3231                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3232                 if (r_loadgloss)
3233                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3234                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3235                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3236                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3237         }
3238
3239         // _norm is the name used by tenebrae and has been adopted as standard
3240         if (r_loadnormalmap && skinframe->nmap == NULL)
3241         {
3242                 mymiplevel = savemiplevel;
3243                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3244                 {
3245                         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);
3246                         Mem_Free(pixels);
3247                         pixels = NULL;
3248                 }
3249                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3250                 {
3251                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3252                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3253                         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);
3254                         Mem_Free(pixels);
3255                         Mem_Free(bumppixels);
3256                 }
3257                 else if (r_shadow_bumpscale_basetexture.value > 0)
3258                 {
3259                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3260                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3261                         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);
3262                         Mem_Free(pixels);
3263                 }
3264                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3265                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3266         }
3267
3268         // _luma is supported only for tenebrae compatibility
3269         // _glow is the preferred name
3270         mymiplevel = savemiplevel;
3271         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))))
3272         {
3273                 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);
3274                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3275                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3276                 Mem_Free(pixels);pixels = NULL;
3277         }
3278
3279         mymiplevel = savemiplevel;
3280         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3281         {
3282                 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);
3283                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3284                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3285                 Mem_Free(pixels);
3286                 pixels = NULL;
3287         }
3288
3289         mymiplevel = savemiplevel;
3290         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3291         {
3292                 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);
3293                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3294                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3295                 Mem_Free(pixels);
3296                 pixels = NULL;
3297         }
3298
3299         mymiplevel = savemiplevel;
3300         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3301         {
3302                 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);
3303                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3304                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3305                 Mem_Free(pixels);
3306                 pixels = NULL;
3307         }
3308
3309         mymiplevel = savemiplevel;
3310         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3311         {
3312                 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);
3313                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3314                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3315                 Mem_Free(pixels);
3316                 pixels = NULL;
3317         }
3318
3319         if (basepixels)
3320                 Mem_Free(basepixels);
3321
3322         return skinframe;
3323 }
3324
3325 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3326 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3327 {
3328         int i;
3329         unsigned char *temp1, *temp2;
3330         skinframe_t *skinframe;
3331
3332         if (cls.state == ca_dedicated)
3333                 return NULL;
3334
3335         // if already loaded just return it, otherwise make a new skinframe
3336         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3337         if (skinframe && skinframe->base)
3338                 return skinframe;
3339
3340         skinframe->stain = NULL;
3341         skinframe->merged = NULL;
3342         skinframe->base = NULL;
3343         skinframe->pants = NULL;
3344         skinframe->shirt = NULL;
3345         skinframe->nmap = NULL;
3346         skinframe->gloss = NULL;
3347         skinframe->glow = NULL;
3348         skinframe->fog = NULL;
3349         skinframe->reflect = NULL;
3350         skinframe->hasalpha = false;
3351
3352         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3353         if (!skindata)
3354                 return NULL;
3355
3356         if (developer_loading.integer)
3357                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3358
3359         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3360         {
3361                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3362                 temp2 = temp1 + width * height * 4;
3363                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3364                 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);
3365                 Mem_Free(temp1);
3366         }
3367         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3368         if (textureflags & TEXF_ALPHA)
3369         {
3370                 for (i = 3;i < width * height * 4;i += 4)
3371                 {
3372                         if (skindata[i] < 255)
3373                         {
3374                                 skinframe->hasalpha = true;
3375                                 break;
3376                         }
3377                 }
3378                 if (r_loadfog && skinframe->hasalpha)
3379                 {
3380                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3381                         memcpy(fogpixels, skindata, width * height * 4);
3382                         for (i = 0;i < width * height * 4;i += 4)
3383                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3384                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3385                         Mem_Free(fogpixels);
3386                 }
3387         }
3388
3389         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3390         //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]);
3391
3392         return skinframe;
3393 }
3394
3395 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3396 {
3397         int i;
3398         int featuresmask;
3399         skinframe_t *skinframe;
3400
3401         if (cls.state == ca_dedicated)
3402                 return NULL;
3403
3404         // if already loaded just return it, otherwise make a new skinframe
3405         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3406         if (skinframe && skinframe->base)
3407                 return skinframe;
3408
3409         skinframe->stain = NULL;
3410         skinframe->merged = NULL;
3411         skinframe->base = NULL;
3412         skinframe->pants = NULL;
3413         skinframe->shirt = NULL;
3414         skinframe->nmap = NULL;
3415         skinframe->gloss = NULL;
3416         skinframe->glow = NULL;
3417         skinframe->fog = NULL;
3418         skinframe->reflect = NULL;
3419         skinframe->hasalpha = false;
3420
3421         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3422         if (!skindata)
3423                 return NULL;
3424
3425         if (developer_loading.integer)
3426                 Con_Printf("loading quake skin \"%s\"\n", name);
3427
3428         // 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)
3429         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3430         memcpy(skinframe->qpixels, skindata, width*height);
3431         skinframe->qwidth = width;
3432         skinframe->qheight = height;
3433
3434         featuresmask = 0;
3435         for (i = 0;i < width * height;i++)
3436                 featuresmask |= palette_featureflags[skindata[i]];
3437
3438         skinframe->hasalpha = false;
3439         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3440         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3441         skinframe->qgeneratemerged = true;
3442         skinframe->qgeneratebase = skinframe->qhascolormapping;
3443         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3444
3445         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3446         //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]);
3447
3448         return skinframe;
3449 }
3450
3451 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3452 {
3453         int width;
3454         int height;
3455         unsigned char *skindata;
3456
3457         if (!skinframe->qpixels)
3458                 return;
3459
3460         if (!skinframe->qhascolormapping)
3461                 colormapped = false;
3462
3463         if (colormapped)
3464         {
3465                 if (!skinframe->qgeneratebase)
3466                         return;
3467         }
3468         else
3469         {
3470                 if (!skinframe->qgeneratemerged)
3471                         return;
3472         }
3473
3474         width = skinframe->qwidth;
3475         height = skinframe->qheight;
3476         skindata = skinframe->qpixels;
3477
3478         if (skinframe->qgeneratenmap)
3479         {
3480                 unsigned char *temp1, *temp2;
3481                 skinframe->qgeneratenmap = false;
3482                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3483                 temp2 = temp1 + width * height * 4;
3484                 // use either a custom palette or the quake palette
3485                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3486                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3487                 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);
3488                 Mem_Free(temp1);
3489         }
3490
3491         if (skinframe->qgenerateglow)
3492         {
3493                 skinframe->qgenerateglow = false;
3494                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3495         }
3496
3497         if (colormapped)
3498         {
3499                 skinframe->qgeneratebase = false;
3500                 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);
3501                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3502                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3503         }
3504         else
3505         {
3506                 skinframe->qgeneratemerged = false;
3507                 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);
3508         }
3509
3510         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3511         {
3512                 Mem_Free(skinframe->qpixels);
3513                 skinframe->qpixels = NULL;
3514         }
3515 }
3516
3517 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)
3518 {
3519         int i;
3520         skinframe_t *skinframe;
3521
3522         if (cls.state == ca_dedicated)
3523                 return NULL;
3524
3525         // if already loaded just return it, otherwise make a new skinframe
3526         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3527         if (skinframe && skinframe->base)
3528                 return skinframe;
3529
3530         skinframe->stain = NULL;
3531         skinframe->merged = NULL;
3532         skinframe->base = NULL;
3533         skinframe->pants = NULL;
3534         skinframe->shirt = NULL;
3535         skinframe->nmap = NULL;
3536         skinframe->gloss = NULL;
3537         skinframe->glow = NULL;
3538         skinframe->fog = NULL;
3539         skinframe->reflect = NULL;
3540         skinframe->hasalpha = false;
3541
3542         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3543         if (!skindata)
3544                 return NULL;
3545
3546         if (developer_loading.integer)
3547                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3548
3549         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3550         if (textureflags & TEXF_ALPHA)
3551         {
3552                 for (i = 0;i < width * height;i++)
3553                 {
3554                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3555                         {
3556                                 skinframe->hasalpha = true;
3557                                 break;
3558                         }
3559                 }
3560                 if (r_loadfog && skinframe->hasalpha)
3561                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3562         }
3563
3564         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3565         //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]);
3566
3567         return skinframe;
3568 }
3569
3570 skinframe_t *R_SkinFrame_LoadMissing(void)
3571 {
3572         skinframe_t *skinframe;
3573
3574         if (cls.state == ca_dedicated)
3575                 return NULL;
3576
3577         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3578         skinframe->stain = NULL;
3579         skinframe->merged = NULL;
3580         skinframe->base = NULL;
3581         skinframe->pants = NULL;
3582         skinframe->shirt = NULL;
3583         skinframe->nmap = NULL;
3584         skinframe->gloss = NULL;
3585         skinframe->glow = NULL;
3586         skinframe->fog = NULL;
3587         skinframe->reflect = NULL;
3588         skinframe->hasalpha = false;
3589
3590         skinframe->avgcolor[0] = rand() / RAND_MAX;
3591         skinframe->avgcolor[1] = rand() / RAND_MAX;
3592         skinframe->avgcolor[2] = rand() / RAND_MAX;
3593         skinframe->avgcolor[3] = 1;
3594
3595         return skinframe;
3596 }
3597
3598 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3599 typedef struct suffixinfo_s
3600 {
3601         const char *suffix;
3602         qboolean flipx, flipy, flipdiagonal;
3603 }
3604 suffixinfo_t;
3605 static suffixinfo_t suffix[3][6] =
3606 {
3607         {
3608                 {"px",   false, false, false},
3609                 {"nx",   false, false, false},
3610                 {"py",   false, false, false},
3611                 {"ny",   false, false, false},
3612                 {"pz",   false, false, false},
3613                 {"nz",   false, false, false}
3614         },
3615         {
3616                 {"posx", false, false, false},
3617                 {"negx", false, false, false},
3618                 {"posy", false, false, false},
3619                 {"negy", false, false, false},
3620                 {"posz", false, false, false},
3621                 {"negz", false, false, false}
3622         },
3623         {
3624                 {"rt",    true, false,  true},
3625                 {"lf",   false,  true,  true},
3626                 {"ft",    true,  true, false},
3627                 {"bk",   false, false, false},
3628                 {"up",    true, false,  true},
3629                 {"dn",    true, false,  true}
3630         }
3631 };
3632
3633 static int componentorder[4] = {0, 1, 2, 3};
3634
3635 rtexture_t *R_LoadCubemap(const char *basename)
3636 {
3637         int i, j, cubemapsize;
3638         unsigned char *cubemappixels, *image_buffer;
3639         rtexture_t *cubemaptexture;
3640         char name[256];
3641         // must start 0 so the first loadimagepixels has no requested width/height
3642         cubemapsize = 0;
3643         cubemappixels = NULL;
3644         cubemaptexture = NULL;
3645         // keep trying different suffix groups (posx, px, rt) until one loads
3646         for (j = 0;j < 3 && !cubemappixels;j++)
3647         {
3648                 // load the 6 images in the suffix group
3649                 for (i = 0;i < 6;i++)
3650                 {
3651                         // generate an image name based on the base and and suffix
3652                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3653                         // load it
3654                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3655                         {
3656                                 // an image loaded, make sure width and height are equal
3657                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3658                                 {
3659                                         // if this is the first image to load successfully, allocate the cubemap memory
3660                                         if (!cubemappixels && image_width >= 1)
3661                                         {
3662                                                 cubemapsize = image_width;
3663                                                 // note this clears to black, so unavailable sides are black
3664                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3665                                         }
3666                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3667                                         if (cubemappixels)
3668                                                 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);
3669                                 }
3670                                 else
3671                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3672                                 // free the image
3673                                 Mem_Free(image_buffer);
3674                         }
3675                 }
3676         }
3677         // if a cubemap loaded, upload it
3678         if (cubemappixels)
3679         {
3680                 if (developer_loading.integer)
3681                         Con_Printf("loading cubemap \"%s\"\n", basename);
3682
3683                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3684                 Mem_Free(cubemappixels);
3685         }
3686         else
3687         {
3688                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3689                 if (developer_loading.integer)
3690                 {
3691                         Con_Printf("(tried tried images ");
3692                         for (j = 0;j < 3;j++)
3693                                 for (i = 0;i < 6;i++)
3694                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3695                         Con_Print(" and was unable to find any of them).\n");
3696                 }
3697         }
3698         return cubemaptexture;
3699 }
3700
3701 rtexture_t *R_GetCubemap(const char *basename)
3702 {
3703         int i;
3704         for (i = 0;i < r_texture_numcubemaps;i++)
3705                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3706                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3707         if (i >= MAX_CUBEMAPS)
3708                 return r_texture_whitecube;
3709         r_texture_numcubemaps++;
3710         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3711         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3712         return r_texture_cubemaps[i].texture;
3713 }
3714
3715 void R_FreeCubemaps(void)
3716 {
3717         int i;
3718         for (i = 0;i < r_texture_numcubemaps;i++)
3719         {
3720                 if (developer_loading.integer)
3721                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3722                 if (r_texture_cubemaps[i].texture)
3723                         R_FreeTexture(r_texture_cubemaps[i].texture);
3724         }
3725         r_texture_numcubemaps = 0;
3726 }
3727
3728 void R_Main_FreeViewCache(void)
3729 {
3730         if (r_refdef.viewcache.entityvisible)
3731                 Mem_Free(r_refdef.viewcache.entityvisible);
3732         if (r_refdef.viewcache.world_pvsbits)
3733                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3734         if (r_refdef.viewcache.world_leafvisible)
3735                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3736         if (r_refdef.viewcache.world_surfacevisible)
3737                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3738         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3739 }
3740
3741 void R_Main_ResizeViewCache(void)
3742 {
3743         int numentities = r_refdef.scene.numentities;
3744         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3745         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3746         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3747         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3748         if (r_refdef.viewcache.maxentities < numentities)
3749         {
3750                 r_refdef.viewcache.maxentities = numentities;
3751                 if (r_refdef.viewcache.entityvisible)
3752                         Mem_Free(r_refdef.viewcache.entityvisible);
3753                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3754         }
3755         if (r_refdef.viewcache.world_numclusters != numclusters)
3756         {
3757                 r_refdef.viewcache.world_numclusters = numclusters;
3758                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3759                 if (r_refdef.viewcache.world_pvsbits)
3760                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3761                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3762         }
3763         if (r_refdef.viewcache.world_numleafs != numleafs)
3764         {
3765                 r_refdef.viewcache.world_numleafs = numleafs;
3766                 if (r_refdef.viewcache.world_leafvisible)
3767                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3768                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3769         }
3770         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3771         {
3772                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3773                 if (r_refdef.viewcache.world_surfacevisible)
3774                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3775                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3776         }
3777 }
3778
3779 extern rtexture_t *loadingscreentexture;
3780 void gl_main_start(void)
3781 {
3782         loadingscreentexture = NULL;
3783         r_texture_blanknormalmap = NULL;
3784         r_texture_white = NULL;
3785         r_texture_grey128 = NULL;
3786         r_texture_black = NULL;
3787         r_texture_whitecube = NULL;
3788         r_texture_normalizationcube = NULL;
3789         r_texture_fogattenuation = NULL;
3790         r_texture_fogheighttexture = NULL;
3791         r_texture_gammaramps = NULL;
3792         r_texture_numcubemaps = 0;
3793
3794         r_loaddds = r_texture_dds_load.integer != 0;
3795         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3796
3797         switch(vid.renderpath)
3798         {
3799         case RENDERPATH_GL20:
3800         case RENDERPATH_D3D9:
3801         case RENDERPATH_D3D10:
3802         case RENDERPATH_D3D11:
3803         case RENDERPATH_SOFT:
3804                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3805                 Cvar_SetValueQuick(&gl_combine, 1);
3806                 Cvar_SetValueQuick(&r_glsl, 1);
3807                 r_loadnormalmap = true;
3808                 r_loadgloss = true;
3809                 r_loadfog = false;
3810                 break;
3811         case RENDERPATH_GL13:
3812                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3813                 Cvar_SetValueQuick(&gl_combine, 1);
3814                 Cvar_SetValueQuick(&r_glsl, 0);
3815                 r_loadnormalmap = false;
3816                 r_loadgloss = false;
3817                 r_loadfog = true;
3818                 break;
3819         case RENDERPATH_GL11:
3820                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3821                 Cvar_SetValueQuick(&gl_combine, 0);
3822                 Cvar_SetValueQuick(&r_glsl, 0);
3823                 r_loadnormalmap = false;
3824                 r_loadgloss = false;
3825                 r_loadfog = true;
3826                 break;
3827         case RENDERPATH_GLES2:
3828                 Cvar_SetValueQuick(&r_textureunits, 1);
3829                 Cvar_SetValueQuick(&gl_combine, 1);
3830                 Cvar_SetValueQuick(&r_glsl, 1);
3831                 r_loadnormalmap = true;
3832                 r_loadgloss = false;
3833                 r_loadfog = false;
3834                 break;
3835         }
3836
3837         R_AnimCache_Free();
3838         R_FrameData_Reset();
3839
3840         r_numqueries = 0;
3841         r_maxqueries = 0;
3842         memset(r_queries, 0, sizeof(r_queries));
3843
3844         r_qwskincache = NULL;
3845         r_qwskincache_size = 0;
3846
3847         // set up r_skinframe loading system for textures
3848         memset(&r_skinframe, 0, sizeof(r_skinframe));
3849         r_skinframe.loadsequence = 1;
3850         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3851
3852         r_main_texturepool = R_AllocTexturePool();
3853         R_BuildBlankTextures();
3854         R_BuildNoTexture();
3855         if (vid.support.arb_texture_cube_map)
3856         {
3857                 R_BuildWhiteCube();
3858                 R_BuildNormalizationCube();
3859         }
3860         r_texture_fogattenuation = NULL;
3861         r_texture_fogheighttexture = NULL;
3862         r_texture_gammaramps = NULL;
3863         //r_texture_fogintensity = NULL;
3864         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3865         memset(&r_waterstate, 0, sizeof(r_waterstate));
3866         r_glsl_permutation = NULL;
3867         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3868         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3869         glslshaderstring = NULL;
3870 #ifdef SUPPORTD3D
3871         r_hlsl_permutation = NULL;
3872         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3873         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3874 #endif
3875         hlslshaderstring = NULL;
3876         memset(&r_svbsp, 0, sizeof (r_svbsp));
3877
3878         r_refdef.fogmasktable_density = 0;
3879 }
3880
3881 void gl_main_shutdown(void)
3882 {
3883         R_AnimCache_Free();
3884         R_FrameData_Reset();
3885
3886         R_Main_FreeViewCache();
3887
3888         switch(vid.renderpath)
3889         {
3890         case RENDERPATH_GL11:
3891         case RENDERPATH_GL13:
3892         case RENDERPATH_GL20:
3893         case RENDERPATH_GLES2:
3894                 if (r_maxqueries)
3895                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3896                 break;
3897         case RENDERPATH_D3D9:
3898                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3899                 break;
3900         case RENDERPATH_D3D10:
3901                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3902                 break;
3903         case RENDERPATH_D3D11:
3904                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3905                 break;
3906         case RENDERPATH_SOFT:
3907                 break;
3908         }
3909
3910         r_numqueries = 0;
3911         r_maxqueries = 0;
3912         memset(r_queries, 0, sizeof(r_queries));
3913
3914         r_qwskincache = NULL;
3915         r_qwskincache_size = 0;
3916
3917         // clear out the r_skinframe state
3918         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3919         memset(&r_skinframe, 0, sizeof(r_skinframe));
3920
3921         if (r_svbsp.nodes)
3922                 Mem_Free(r_svbsp.nodes);
3923         memset(&r_svbsp, 0, sizeof (r_svbsp));
3924         R_FreeTexturePool(&r_main_texturepool);
3925         loadingscreentexture = NULL;
3926         r_texture_blanknormalmap = NULL;
3927         r_texture_white = NULL;
3928         r_texture_grey128 = NULL;
3929         r_texture_black = NULL;
3930         r_texture_whitecube = NULL;
3931         r_texture_normalizationcube = NULL;
3932         r_texture_fogattenuation = NULL;
3933         r_texture_fogheighttexture = NULL;
3934         r_texture_gammaramps = NULL;
3935         r_texture_numcubemaps = 0;
3936         //r_texture_fogintensity = NULL;
3937         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3938         memset(&r_waterstate, 0, sizeof(r_waterstate));
3939         R_GLSL_Restart_f();
3940
3941         r_glsl_permutation = NULL;
3942         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3943         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3944         glslshaderstring = NULL;
3945 #ifdef SUPPORTD3D
3946         r_hlsl_permutation = NULL;
3947         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3948         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3949 #endif
3950         hlslshaderstring = NULL;
3951 }
3952
3953 extern void CL_ParseEntityLump(char *entitystring);
3954 void gl_main_newmap(void)
3955 {
3956         // FIXME: move this code to client
3957         char *entities, entname[MAX_QPATH];
3958         if (r_qwskincache)
3959                 Mem_Free(r_qwskincache);
3960         r_qwskincache = NULL;
3961         r_qwskincache_size = 0;
3962         if (cl.worldmodel)
3963         {
3964                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3965                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3966                 {
3967                         CL_ParseEntityLump(entities);
3968                         Mem_Free(entities);
3969                         return;
3970                 }
3971                 if (cl.worldmodel->brush.entities)
3972                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3973         }
3974         R_Main_FreeViewCache();
3975
3976         R_FrameData_Reset();
3977 }
3978
3979 void GL_Main_Init(void)
3980 {
3981         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3982
3983         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3984         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3985         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3986         if (gamemode == GAME_NEHAHRA)
3987         {
3988                 Cvar_RegisterVariable (&gl_fogenable);
3989                 Cvar_RegisterVariable (&gl_fogdensity);
3990                 Cvar_RegisterVariable (&gl_fogred);
3991                 Cvar_RegisterVariable (&gl_foggreen);
3992                 Cvar_RegisterVariable (&gl_fogblue);
3993                 Cvar_RegisterVariable (&gl_fogstart);
3994                 Cvar_RegisterVariable (&gl_fogend);
3995                 Cvar_RegisterVariable (&gl_skyclip);
3996         }
3997         Cvar_RegisterVariable(&r_motionblur);
3998         Cvar_RegisterVariable(&r_motionblur_maxblur);
3999         Cvar_RegisterVariable(&r_motionblur_bmin);
4000         Cvar_RegisterVariable(&r_motionblur_vmin);
4001         Cvar_RegisterVariable(&r_motionblur_vmax);
4002         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4003         Cvar_RegisterVariable(&r_motionblur_randomize);
4004         Cvar_RegisterVariable(&r_damageblur);
4005         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4006         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4007         Cvar_RegisterVariable(&r_equalize_entities_by);
4008         Cvar_RegisterVariable(&r_equalize_entities_to);
4009         Cvar_RegisterVariable(&r_depthfirst);
4010         Cvar_RegisterVariable(&r_useinfinitefarclip);
4011         Cvar_RegisterVariable(&r_farclip_base);
4012         Cvar_RegisterVariable(&r_farclip_world);
4013         Cvar_RegisterVariable(&r_nearclip);
4014         Cvar_RegisterVariable(&r_showbboxes);
4015         Cvar_RegisterVariable(&r_showsurfaces);
4016         Cvar_RegisterVariable(&r_showtris);
4017         Cvar_RegisterVariable(&r_shownormals);
4018         Cvar_RegisterVariable(&r_showlighting);
4019         Cvar_RegisterVariable(&r_showshadowvolumes);
4020         Cvar_RegisterVariable(&r_showcollisionbrushes);
4021         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4022         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4023         Cvar_RegisterVariable(&r_showdisabledepthtest);
4024         Cvar_RegisterVariable(&r_drawportals);
4025         Cvar_RegisterVariable(&r_drawentities);
4026         Cvar_RegisterVariable(&r_draw2d);
4027         Cvar_RegisterVariable(&r_drawworld);
4028         Cvar_RegisterVariable(&r_cullentities_trace);
4029         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4030         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4031         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4032         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4033         Cvar_RegisterVariable(&r_drawviewmodel);
4034         Cvar_RegisterVariable(&r_drawexteriormodel);
4035         Cvar_RegisterVariable(&r_speeds);
4036         Cvar_RegisterVariable(&r_fullbrights);
4037         Cvar_RegisterVariable(&r_wateralpha);
4038         Cvar_RegisterVariable(&r_dynamic);
4039         Cvar_RegisterVariable(&r_fakelight);
4040         Cvar_RegisterVariable(&r_fakelight_intensity);
4041         Cvar_RegisterVariable(&r_fullbright);
4042         Cvar_RegisterVariable(&r_shadows);
4043         Cvar_RegisterVariable(&r_shadows_darken);
4044         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4045         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4046         Cvar_RegisterVariable(&r_shadows_throwdistance);
4047         Cvar_RegisterVariable(&r_shadows_throwdirection);
4048         Cvar_RegisterVariable(&r_shadows_focus);
4049         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4050         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4051         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4052         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4053         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4054         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4055         Cvar_RegisterVariable(&r_fog_exp2);
4056         Cvar_RegisterVariable(&r_drawfog);
4057         Cvar_RegisterVariable(&r_transparentdepthmasking);
4058         Cvar_RegisterVariable(&r_texture_dds_load);
4059         Cvar_RegisterVariable(&r_texture_dds_save);
4060         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4061         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4062         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4063         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4064         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4065         Cvar_RegisterVariable(&r_textureunits);
4066         Cvar_RegisterVariable(&gl_combine);
4067         Cvar_RegisterVariable(&r_glsl);
4068         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4069         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4070         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4071         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4072         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4073         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4074         Cvar_RegisterVariable(&r_glsl_postprocess);
4075         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4076         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4077         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4078         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4079         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4080         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4081         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4082         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4083
4084         Cvar_RegisterVariable(&r_water);
4085         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4086         Cvar_RegisterVariable(&r_water_clippingplanebias);
4087         Cvar_RegisterVariable(&r_water_refractdistort);
4088         Cvar_RegisterVariable(&r_water_reflectdistort);
4089         Cvar_RegisterVariable(&r_water_scissormode);
4090         Cvar_RegisterVariable(&r_lerpsprites);
4091         Cvar_RegisterVariable(&r_lerpmodels);
4092         Cvar_RegisterVariable(&r_lerplightstyles);
4093         Cvar_RegisterVariable(&r_waterscroll);
4094         Cvar_RegisterVariable(&r_bloom);
4095         Cvar_RegisterVariable(&r_bloom_colorscale);
4096         Cvar_RegisterVariable(&r_bloom_brighten);
4097         Cvar_RegisterVariable(&r_bloom_blur);
4098         Cvar_RegisterVariable(&r_bloom_resolution);
4099         Cvar_RegisterVariable(&r_bloom_colorexponent);
4100         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4101         Cvar_RegisterVariable(&r_hdr);
4102         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4103         Cvar_RegisterVariable(&r_hdr_glowintensity);
4104         Cvar_RegisterVariable(&r_hdr_range);
4105         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4106         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4107         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4108         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4109         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4110         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4111         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4112         Cvar_RegisterVariable(&developer_texturelogging);
4113         Cvar_RegisterVariable(&gl_lightmaps);
4114         Cvar_RegisterVariable(&r_test);
4115         Cvar_RegisterVariable(&r_glsl_saturation);
4116         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4117         Cvar_RegisterVariable(&r_framedatasize);
4118         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4119                 Cvar_SetValue("r_fullbrights", 0);
4120         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4121
4122         Cvar_RegisterVariable(&r_track_sprites);
4123         Cvar_RegisterVariable(&r_track_sprites_flags);
4124         Cvar_RegisterVariable(&r_track_sprites_scalew);
4125         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4126         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4127         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4128         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4129         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4130 }
4131
4132 extern void R_Textures_Init(void);
4133 extern void GL_Draw_Init(void);
4134 extern void GL_Main_Init(void);
4135 extern void R_Shadow_Init(void);
4136 extern void R_Sky_Init(void);
4137 extern void GL_Surf_Init(void);
4138 extern void R_Particles_Init(void);
4139 extern void R_Explosion_Init(void);
4140 extern void gl_backend_init(void);
4141 extern void Sbar_Init(void);
4142 extern void R_LightningBeams_Init(void);
4143 extern void Mod_RenderInit(void);
4144 extern void Font_Init(void);
4145
4146 void Render_Init(void)
4147 {
4148         gl_backend_init();
4149         R_Textures_Init();
4150         GL_Main_Init();
4151         Font_Init();
4152         GL_Draw_Init();
4153         R_Shadow_Init();
4154         R_Sky_Init();
4155         GL_Surf_Init();
4156         Sbar_Init();
4157         R_Particles_Init();
4158         R_Explosion_Init();
4159         R_LightningBeams_Init();
4160         Mod_RenderInit();
4161 }
4162
4163 /*
4164 ===============
4165 GL_Init
4166 ===============
4167 */
4168 extern char *ENGINE_EXTENSIONS;
4169 void GL_Init (void)
4170 {
4171         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4172         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4173         gl_version = (const char *)qglGetString(GL_VERSION);
4174         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4175
4176         if (!gl_extensions)
4177                 gl_extensions = "";
4178         if (!gl_platformextensions)
4179                 gl_platformextensions = "";
4180
4181         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4182         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4183         Con_Printf("GL_VERSION: %s\n", gl_version);
4184         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4185         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4186
4187         VID_CheckExtensions();
4188
4189         // LordHavoc: report supported extensions
4190         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4191
4192         // clear to black (loading plaque will be seen over this)
4193         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4194 }
4195
4196 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4197 {
4198         int i;
4199         mplane_t *p;
4200         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4201         {
4202                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4203                 if (i == 4)
4204                         continue;
4205                 p = r_refdef.view.frustum + i;
4206                 switch(p->signbits)
4207                 {
4208                 default:
4209                 case 0:
4210                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4211                                 return true;
4212                         break;
4213                 case 1:
4214                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4215                                 return true;
4216                         break;
4217                 case 2:
4218                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4219                                 return true;
4220                         break;
4221                 case 3:
4222                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4223                                 return true;
4224                         break;
4225                 case 4:
4226                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4227                                 return true;
4228                         break;
4229                 case 5:
4230                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4231                                 return true;
4232                         break;
4233                 case 6:
4234                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4235                                 return true;
4236                         break;
4237                 case 7:
4238                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4239                                 return true;
4240                         break;
4241                 }
4242         }
4243         return false;
4244 }
4245
4246 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4247 {
4248         int i;
4249         const mplane_t *p;
4250         for (i = 0;i < numplanes;i++)
4251         {
4252                 p = planes + i;
4253                 switch(p->signbits)
4254                 {
4255                 default:
4256                 case 0:
4257                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4258                                 return true;
4259                         break;
4260                 case 1:
4261                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4262                                 return true;
4263                         break;
4264                 case 2:
4265                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4266                                 return true;
4267                         break;
4268                 case 3:
4269                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4270                                 return true;
4271                         break;
4272                 case 4:
4273                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4274                                 return true;
4275                         break;
4276                 case 5:
4277                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4278                                 return true;
4279                         break;
4280                 case 6:
4281                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4282                                 return true;
4283                         break;
4284                 case 7:
4285                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4286                                 return true;
4287                         break;
4288                 }
4289         }
4290         return false;
4291 }
4292
4293 //==================================================================================
4294
4295 // LordHavoc: this stores temporary data used within the same frame
4296
4297 typedef struct r_framedata_mem_s
4298 {
4299         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4300         size_t size; // how much usable space
4301         size_t current; // how much space in use
4302         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4303         size_t wantedsize; // how much space was allocated
4304         unsigned char *data; // start of real data (16byte aligned)
4305 }
4306 r_framedata_mem_t;
4307
4308 static r_framedata_mem_t *r_framedata_mem;
4309
4310 void R_FrameData_Reset(void)
4311 {
4312         while (r_framedata_mem)
4313         {
4314                 r_framedata_mem_t *next = r_framedata_mem->purge;
4315                 Mem_Free(r_framedata_mem);
4316                 r_framedata_mem = next;
4317         }
4318 }
4319
4320 void R_FrameData_Resize(void)
4321 {
4322         size_t wantedsize;
4323         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4324         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4325         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4326         {
4327                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4328                 newmem->wantedsize = wantedsize;
4329                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4330                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4331                 newmem->current = 0;
4332                 newmem->mark = 0;
4333                 newmem->purge = r_framedata_mem;
4334                 r_framedata_mem = newmem;
4335         }
4336 }
4337
4338 void R_FrameData_NewFrame(void)
4339 {
4340         R_FrameData_Resize();
4341         if (!r_framedata_mem)
4342                 return;
4343         // if we ran out of space on the last frame, free the old memory now
4344         while (r_framedata_mem->purge)
4345         {
4346                 // repeatedly remove the second item in the list, leaving only head
4347                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4348                 Mem_Free(r_framedata_mem->purge);
4349                 r_framedata_mem->purge = next;
4350         }
4351         // reset the current mem pointer
4352         r_framedata_mem->current = 0;
4353         r_framedata_mem->mark = 0;
4354 }
4355
4356 void *R_FrameData_Alloc(size_t size)
4357 {
4358         void *data;
4359
4360         // align to 16 byte boundary - the data pointer is already aligned, so we
4361         // only need to ensure the size of every allocation is also aligned
4362         size = (size + 15) & ~15;
4363
4364         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4365         {
4366                 // emergency - we ran out of space, allocate more memory
4367                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4368                 R_FrameData_Resize();
4369         }
4370
4371         data = r_framedata_mem->data + r_framedata_mem->current;
4372         r_framedata_mem->current += size;
4373
4374         // count the usage for stats
4375         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4376         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4377
4378         return (void *)data;
4379 }
4380
4381 void *R_FrameData_Store(size_t size, void *data)
4382 {
4383         void *d = R_FrameData_Alloc(size);
4384         if (d && data)
4385                 memcpy(d, data, size);
4386         return d;
4387 }
4388
4389 void R_FrameData_SetMark(void)
4390 {
4391         if (!r_framedata_mem)
4392                 return;
4393         r_framedata_mem->mark = r_framedata_mem->current;
4394 }
4395
4396 void R_FrameData_ReturnToMark(void)
4397 {
4398         if (!r_framedata_mem)
4399                 return;
4400         r_framedata_mem->current = r_framedata_mem->mark;
4401 }
4402
4403 //==================================================================================
4404
4405 // LordHavoc: animcache originally written by Echon, rewritten since then
4406
4407 /**
4408  * Animation cache prevents re-generating mesh data for an animated model
4409  * multiple times in one frame for lighting, shadowing, reflections, etc.
4410  */
4411
4412 void R_AnimCache_Free(void)
4413 {
4414 }
4415
4416 void R_AnimCache_ClearCache(void)
4417 {
4418         int i;
4419         entity_render_t *ent;
4420
4421         for (i = 0;i < r_refdef.scene.numentities;i++)
4422         {
4423                 ent = r_refdef.scene.entities[i];
4424                 ent->animcache_vertex3f = NULL;
4425                 ent->animcache_normal3f = NULL;
4426                 ent->animcache_svector3f = NULL;
4427                 ent->animcache_tvector3f = NULL;
4428                 ent->animcache_vertexmesh = NULL;
4429                 ent->animcache_vertex3fbuffer = NULL;
4430                 ent->animcache_vertexmeshbuffer = NULL;
4431         }
4432 }
4433
4434 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4435 {
4436         int i;
4437
4438         // check if we need the meshbuffers
4439         if (!vid.useinterleavedarrays)
4440                 return;
4441
4442         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4443                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4444         // TODO: upload vertex3f buffer?
4445         if (ent->animcache_vertexmesh)
4446         {
4447                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4448                 for (i = 0;i < numvertices;i++)
4449                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4450                 if (ent->animcache_svector3f)
4451                         for (i = 0;i < numvertices;i++)
4452                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4453                 if (ent->animcache_tvector3f)
4454                         for (i = 0;i < numvertices;i++)
4455                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4456                 if (ent->animcache_normal3f)
4457                         for (i = 0;i < numvertices;i++)
4458                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4459                 // TODO: upload vertexmeshbuffer?
4460         }
4461 }
4462
4463 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4464 {
4465         dp_model_t *model = ent->model;
4466         int numvertices;
4467         // see if it's already cached this frame
4468         if (ent->animcache_vertex3f)
4469         {
4470                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4471                 if (wantnormals || wanttangents)
4472                 {
4473                         if (ent->animcache_normal3f)
4474                                 wantnormals = false;
4475                         if (ent->animcache_svector3f)
4476                                 wanttangents = false;
4477                         if (wantnormals || wanttangents)
4478                         {
4479                                 numvertices = model->surfmesh.num_vertices;
4480                                 if (wantnormals)
4481                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4482                                 if (wanttangents)
4483                                 {
4484                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4485                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4486                                 }
4487                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4488                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4489                         }
4490                 }
4491         }
4492         else
4493         {
4494                 // see if this ent is worth caching
4495                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4496                         return false;
4497                 // get some memory for this entity and generate mesh data
4498                 numvertices = model->surfmesh.num_vertices;
4499                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4500                 if (wantnormals)
4501                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4502                 if (wanttangents)
4503                 {
4504                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4505                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4506                 }
4507                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4508                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4509         }
4510         return true;
4511 }
4512
4513 void R_AnimCache_CacheVisibleEntities(void)
4514 {
4515         int i;
4516         qboolean wantnormals = true;
4517         qboolean wanttangents = !r_showsurfaces.integer;
4518
4519         switch(vid.renderpath)
4520         {
4521         case RENDERPATH_GL20:
4522         case RENDERPATH_D3D9:
4523         case RENDERPATH_D3D10:
4524         case RENDERPATH_D3D11:
4525         case RENDERPATH_GLES2:
4526                 break;
4527         case RENDERPATH_GL13:
4528         case RENDERPATH_GL11:
4529                 wanttangents = false;
4530                 break;
4531         case RENDERPATH_SOFT:
4532                 break;
4533         }
4534
4535         if (r_shownormals.integer)
4536                 wanttangents = wantnormals = true;
4537
4538         // TODO: thread this
4539         // NOTE: R_PrepareRTLights() also caches entities
4540
4541         for (i = 0;i < r_refdef.scene.numentities;i++)
4542                 if (r_refdef.viewcache.entityvisible[i])
4543                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4544 }
4545
4546 //==================================================================================
4547
4548 static void R_View_UpdateEntityLighting (void)
4549 {
4550         int i;
4551         entity_render_t *ent;
4552         vec3_t tempdiffusenormal, avg;
4553         vec_t f, fa, fd, fdd;
4554         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4555
4556         for (i = 0;i < r_refdef.scene.numentities;i++)
4557         {
4558                 ent = r_refdef.scene.entities[i];
4559
4560                 // skip unseen models
4561                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4562                         continue;
4563
4564                 // skip bsp models
4565                 if (ent->model && ent->model->brush.num_leafs)
4566                 {
4567                         // TODO: use modellight for r_ambient settings on world?
4568                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4569                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4570                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4571                         continue;
4572                 }
4573
4574                 // fetch the lighting from the worldmodel data
4575                 VectorClear(ent->modellight_ambient);
4576                 VectorClear(ent->modellight_diffuse);
4577                 VectorClear(tempdiffusenormal);
4578                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4579                 {
4580                         vec3_t org;
4581                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4582
4583                         // complete lightning for lit sprites
4584                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4585                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4586                         {
4587                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4588                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4589                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4590                         }
4591                         else
4592                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4593
4594                         if(ent->flags & RENDER_EQUALIZE)
4595                         {
4596                                 // first fix up ambient lighting...
4597                                 if(r_equalize_entities_minambient.value > 0)
4598                                 {
4599                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4600                                         if(fd > 0)
4601                                         {
4602                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4603                                                 if(fa < r_equalize_entities_minambient.value * fd)
4604                                                 {
4605                                                         // solve:
4606                                                         //   fa'/fd' = minambient
4607                                                         //   fa'+0.25*fd' = fa+0.25*fd
4608                                                         //   ...
4609                                                         //   fa' = fd' * minambient
4610                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4611                                                         //   ...
4612                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4613                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4614                                                         //   ...
4615                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4616                                                         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
4617                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4618                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4619                                                 }
4620                                         }
4621                                 }
4622
4623                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4624                                 {
4625                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4626                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4627                                         f = fa + 0.25 * fd;
4628                                         if(f > 0)
4629                                         {
4630                                                 // adjust brightness and saturation to target
4631                                                 avg[0] = avg[1] = avg[2] = fa / f;
4632                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4633                                                 avg[0] = avg[1] = avg[2] = fd / f;
4634                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4635                                         }
4636                                 }
4637                         }
4638                 }
4639                 else // highly rare
4640                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4641
4642                 // move the light direction into modelspace coordinates for lighting code
4643                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4644                 if(VectorLength2(ent->modellight_lightdir) == 0)
4645                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4646                 VectorNormalize(ent->modellight_lightdir);
4647         }
4648 }
4649
4650 #define MAX_LINEOFSIGHTTRACES 64
4651
4652 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4653 {
4654         int i;
4655         vec3_t boxmins, boxmaxs;
4656         vec3_t start;
4657         vec3_t end;
4658         dp_model_t *model = r_refdef.scene.worldmodel;
4659
4660         if (!model || !model->brush.TraceLineOfSight)
4661                 return true;
4662
4663         // expand the box a little
4664         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4665         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4666         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4667         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4668         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4669         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4670
4671         // return true if eye is inside enlarged box
4672         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4673                 return true;
4674
4675         // try center
4676         VectorCopy(eye, start);
4677         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4678         if (model->brush.TraceLineOfSight(model, start, end))
4679                 return true;
4680
4681         // try various random positions
4682         for (i = 0;i < numsamples;i++)
4683         {
4684                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4685                 if (model->brush.TraceLineOfSight(model, start, end))
4686                         return true;
4687         }
4688
4689         return false;
4690 }
4691
4692
4693 static void R_View_UpdateEntityVisible (void)
4694 {
4695         int i;
4696         int renderimask;
4697         int samples;
4698         entity_render_t *ent;
4699
4700         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4701                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4702                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4703                 :                                                          RENDER_EXTERIORMODEL;
4704         if (!r_drawviewmodel.integer)
4705                 renderimask |= RENDER_VIEWMODEL;
4706         if (!r_drawexteriormodel.integer)
4707                 renderimask |= RENDER_EXTERIORMODEL;
4708         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4709         {
4710                 // worldmodel can check visibility
4711                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4712                 for (i = 0;i < r_refdef.scene.numentities;i++)
4713                 {
4714                         ent = r_refdef.scene.entities[i];
4715                         if (!(ent->flags & renderimask))
4716                         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)))
4717                         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))
4718                                 r_refdef.viewcache.entityvisible[i] = true;
4719                 }
4720                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4721                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4722                 {
4723                         for (i = 0;i < r_refdef.scene.numentities;i++)
4724                         {
4725                                 ent = r_refdef.scene.entities[i];
4726                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4727                                 {
4728                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4729                                         if (samples < 0)
4730                                                 continue; // temp entities do pvs only
4731                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4732                                                 ent->last_trace_visibility = realtime;
4733                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4734                                                 r_refdef.viewcache.entityvisible[i] = 0;
4735                                 }
4736                         }
4737                 }
4738         }
4739         else
4740         {
4741                 // no worldmodel or it can't check visibility
4742                 for (i = 0;i < r_refdef.scene.numentities;i++)
4743                 {
4744                         ent = r_refdef.scene.entities[i];
4745                         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));
4746                 }
4747         }
4748 }
4749
4750 /// only used if skyrendermasked, and normally returns false
4751 int R_DrawBrushModelsSky (void)
4752 {
4753         int i, sky;
4754         entity_render_t *ent;
4755
4756         sky = false;
4757         for (i = 0;i < r_refdef.scene.numentities;i++)
4758         {
4759                 if (!r_refdef.viewcache.entityvisible[i])
4760                         continue;
4761                 ent = r_refdef.scene.entities[i];
4762                 if (!ent->model || !ent->model->DrawSky)
4763                         continue;
4764                 ent->model->DrawSky(ent);
4765                 sky = true;
4766         }
4767         return sky;
4768 }
4769
4770 static void R_DrawNoModel(entity_render_t *ent);
4771 static void R_DrawModels(void)
4772 {
4773         int i;
4774         entity_render_t *ent;
4775
4776         for (i = 0;i < r_refdef.scene.numentities;i++)
4777         {
4778                 if (!r_refdef.viewcache.entityvisible[i])
4779                         continue;
4780                 ent = r_refdef.scene.entities[i];
4781                 r_refdef.stats.entities++;
4782                 if (ent->model && ent->model->Draw != NULL)
4783                         ent->model->Draw(ent);
4784                 else
4785                         R_DrawNoModel(ent);
4786         }
4787 }
4788
4789 static void R_DrawModelsDepth(void)
4790 {
4791         int i;
4792         entity_render_t *ent;
4793
4794         for (i = 0;i < r_refdef.scene.numentities;i++)
4795         {
4796                 if (!r_refdef.viewcache.entityvisible[i])
4797                         continue;
4798                 ent = r_refdef.scene.entities[i];
4799                 if (ent->model && ent->model->DrawDepth != NULL)
4800                         ent->model->DrawDepth(ent);
4801         }
4802 }
4803
4804 static void R_DrawModelsDebug(void)
4805 {
4806         int i;
4807         entity_render_t *ent;
4808
4809         for (i = 0;i < r_refdef.scene.numentities;i++)
4810         {
4811                 if (!r_refdef.viewcache.entityvisible[i])
4812                         continue;
4813                 ent = r_refdef.scene.entities[i];
4814                 if (ent->model && ent->model->DrawDebug != NULL)
4815                         ent->model->DrawDebug(ent);
4816         }
4817 }
4818
4819 static void R_DrawModelsAddWaterPlanes(void)
4820 {
4821         int i;
4822         entity_render_t *ent;
4823
4824         for (i = 0;i < r_refdef.scene.numentities;i++)
4825         {
4826                 if (!r_refdef.viewcache.entityvisible[i])
4827                         continue;
4828                 ent = r_refdef.scene.entities[i];
4829                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4830                         ent->model->DrawAddWaterPlanes(ent);
4831         }
4832 }
4833
4834 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4835 {
4836         if (r_hdr_irisadaptation.integer)
4837         {
4838                 vec3_t ambient;
4839                 vec3_t diffuse;
4840                 vec3_t diffusenormal;
4841                 vec_t brightness;
4842                 vec_t goal;
4843                 vec_t adjust;
4844                 vec_t current;
4845                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4846                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4847                 brightness = max(0.0000001f, brightness);
4848                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4849                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4850                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4851                 current = r_hdr_irisadaptation_value.value;
4852                 if (current < goal)
4853                         current = min(current + adjust, goal);
4854                 else if (current > goal)
4855                         current = max(current - adjust, goal);
4856                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4857                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4858         }
4859         else if (r_hdr_irisadaptation_value.value != 1.0f)
4860                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4861 }
4862
4863 static void R_View_SetFrustum(const int *scissor)
4864 {
4865         int i;
4866         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4867         vec3_t forward, left, up, origin, v;
4868
4869         if(scissor)
4870         {
4871                 // flipped x coordinates (because x points left here)
4872                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4873                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4874
4875                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4876                 switch(vid.renderpath)
4877                 {
4878                         case RENDERPATH_D3D9:
4879                         case RENDERPATH_D3D10:
4880                         case RENDERPATH_D3D11:
4881                         case RENDERPATH_SOFT:
4882                                 // non-flipped y coordinates
4883                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4884                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4885                                 break;
4886                         case RENDERPATH_GL11:
4887                         case RENDERPATH_GL13:
4888                         case RENDERPATH_GL20:
4889                         case RENDERPATH_GLES2:
4890                                 // non-flipped y coordinates
4891                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4892                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4893                                 break;
4894                 }
4895         }
4896
4897         // we can't trust r_refdef.view.forward and friends in reflected scenes
4898         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4899
4900 #if 0
4901         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4902         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4903         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4904         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4905         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4906         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4907         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4908         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4909         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4910         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4911         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4912         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4913 #endif
4914
4915 #if 0
4916         zNear = r_refdef.nearclip;
4917         nudge = 1.0 - 1.0 / (1<<23);
4918         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4919         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4920         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4921         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4922         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4923         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4924         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4925         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4926 #endif
4927
4928
4929
4930 #if 0
4931         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4932         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4933         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4934         r_refdef.view.frustum[0].dist = m[15] - m[12];
4935
4936         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4937         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4938         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4939         r_refdef.view.frustum[1].dist = m[15] + m[12];
4940
4941         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4942         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4943         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4944         r_refdef.view.frustum[2].dist = m[15] - m[13];
4945
4946         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4947         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4948         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4949         r_refdef.view.frustum[3].dist = m[15] + m[13];
4950
4951         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4952         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4953         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4954         r_refdef.view.frustum[4].dist = m[15] - m[14];
4955
4956         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4957         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4958         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4959         r_refdef.view.frustum[5].dist = m[15] + m[14];
4960 #endif
4961
4962         if (r_refdef.view.useperspective)
4963         {
4964                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4965                 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]);
4966                 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]);
4967                 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]);
4968                 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]);
4969
4970                 // then the normals from the corners relative to origin
4971                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4972                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4973                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4974                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4975
4976                 // in a NORMAL view, forward cross left == up
4977                 // in a REFLECTED view, forward cross left == down
4978                 // so our cross products above need to be adjusted for a left handed coordinate system
4979                 CrossProduct(forward, left, v);
4980                 if(DotProduct(v, up) < 0)
4981                 {
4982                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4983                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
4984                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
4985                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
4986                 }
4987
4988                 // Leaving those out was a mistake, those were in the old code, and they
4989                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4990                 // I couldn't reproduce it after adding those normalizations. --blub
4991                 VectorNormalize(r_refdef.view.frustum[0].normal);
4992                 VectorNormalize(r_refdef.view.frustum[1].normal);
4993                 VectorNormalize(r_refdef.view.frustum[2].normal);
4994                 VectorNormalize(r_refdef.view.frustum[3].normal);
4995
4996                 // make the corners absolute
4997                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
4998                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
4999                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5000                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5001
5002                 // one more normal
5003                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5004
5005                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5006                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5007                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5008                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5009                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5010         }
5011         else
5012         {
5013                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5014                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5015                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5016                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5017                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5018                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5019                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5020                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5021                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5022                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5023         }
5024         r_refdef.view.numfrustumplanes = 5;
5025
5026         if (r_refdef.view.useclipplane)
5027         {
5028                 r_refdef.view.numfrustumplanes = 6;
5029                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5030         }
5031
5032         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5033                 PlaneClassify(r_refdef.view.frustum + i);
5034
5035         // LordHavoc: note to all quake engine coders, Quake had a special case
5036         // for 90 degrees which assumed a square view (wrong), so I removed it,
5037         // Quake2 has it disabled as well.
5038
5039         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5040         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5041         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5042         //PlaneClassify(&frustum[0]);
5043
5044         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5045         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5046         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5047         //PlaneClassify(&frustum[1]);
5048
5049         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5050         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5051         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5052         //PlaneClassify(&frustum[2]);
5053
5054         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5055         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5056         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5057         //PlaneClassify(&frustum[3]);
5058
5059         // nearclip plane
5060         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5061         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5062         //PlaneClassify(&frustum[4]);
5063 }
5064
5065 void R_View_UpdateWithScissor(const int *myscissor)
5066 {
5067         R_Main_ResizeViewCache();
5068         R_View_SetFrustum(myscissor);
5069         R_View_WorldVisibility(r_refdef.view.useclipplane);
5070         R_View_UpdateEntityVisible();
5071         R_View_UpdateEntityLighting();
5072 }
5073
5074 void R_View_Update(void)
5075 {
5076         R_Main_ResizeViewCache();
5077         R_View_SetFrustum(NULL);
5078         R_View_WorldVisibility(r_refdef.view.useclipplane);
5079         R_View_UpdateEntityVisible();
5080         R_View_UpdateEntityLighting();
5081 }
5082
5083 void R_SetupView(qboolean allowwaterclippingplane)
5084 {
5085         const float *customclipplane = NULL;
5086         float plane[4];
5087         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5088         {
5089                 // LordHavoc: couldn't figure out how to make this approach the
5090                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5091                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5092                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5093                         dist = r_refdef.view.clipplane.dist;
5094                 plane[0] = r_refdef.view.clipplane.normal[0];
5095                 plane[1] = r_refdef.view.clipplane.normal[1];
5096                 plane[2] = r_refdef.view.clipplane.normal[2];
5097                 plane[3] = dist;
5098                 customclipplane = plane;
5099         }
5100
5101         if (!r_refdef.view.useperspective)
5102                 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);
5103         else if (vid.stencil && r_useinfinitefarclip.integer)
5104                 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);
5105         else
5106                 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);
5107         R_SetViewport(&r_refdef.view.viewport);
5108 }
5109
5110 void R_EntityMatrix(const matrix4x4_t *matrix)
5111 {
5112         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5113         {
5114                 gl_modelmatrixchanged = false;
5115                 gl_modelmatrix = *matrix;
5116                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5117                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5118                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5119                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5120                 CHECKGLERROR
5121                 switch(vid.renderpath)
5122                 {
5123                 case RENDERPATH_D3D9:
5124 #ifdef SUPPORTD3D
5125                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5126                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5127 #endif
5128                         break;
5129                 case RENDERPATH_D3D10:
5130                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5131                         break;
5132                 case RENDERPATH_D3D11:
5133                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5134                         break;
5135                 case RENDERPATH_GL13:
5136                 case RENDERPATH_GL11:
5137                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5138                         break;
5139                 case RENDERPATH_SOFT:
5140                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5141                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5142                         break;
5143                 case RENDERPATH_GL20:
5144                 case RENDERPATH_GLES2:
5145                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5146                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5147                         break;
5148                 }
5149         }
5150 }
5151
5152 void R_ResetViewRendering2D(void)
5153 {
5154         r_viewport_t viewport;
5155         DrawQ_Finish();
5156
5157         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5158         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);
5159         R_SetViewport(&viewport);
5160         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5161         GL_Color(1, 1, 1, 1);
5162         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5163         GL_BlendFunc(GL_ONE, GL_ZERO);
5164         GL_ScissorTest(false);
5165         GL_DepthMask(false);
5166         GL_DepthRange(0, 1);
5167         GL_DepthTest(false);
5168         GL_DepthFunc(GL_LEQUAL);
5169         R_EntityMatrix(&identitymatrix);
5170         R_Mesh_ResetTextureState();
5171         GL_PolygonOffset(0, 0);
5172         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5173         switch(vid.renderpath)
5174         {
5175         case RENDERPATH_GL11:
5176         case RENDERPATH_GL13:
5177         case RENDERPATH_GL20:
5178         case RENDERPATH_GLES2:
5179                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5180                 break;
5181         case RENDERPATH_D3D9:
5182         case RENDERPATH_D3D10:
5183         case RENDERPATH_D3D11:
5184         case RENDERPATH_SOFT:
5185                 break;
5186         }
5187         GL_CullFace(GL_NONE);
5188 }
5189
5190 void R_ResetViewRendering3D(void)
5191 {
5192         DrawQ_Finish();
5193
5194         R_SetupView(true);
5195         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5196         GL_Color(1, 1, 1, 1);
5197         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5198         GL_BlendFunc(GL_ONE, GL_ZERO);
5199         GL_ScissorTest(true);
5200         GL_DepthMask(true);
5201         GL_DepthRange(0, 1);
5202         GL_DepthTest(true);
5203         GL_DepthFunc(GL_LEQUAL);
5204         R_EntityMatrix(&identitymatrix);
5205         R_Mesh_ResetTextureState();
5206         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5207         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5208         switch(vid.renderpath)
5209         {
5210         case RENDERPATH_GL11:
5211         case RENDERPATH_GL13:
5212         case RENDERPATH_GL20:
5213         case RENDERPATH_GLES2:
5214                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5215                 break;
5216         case RENDERPATH_D3D9:
5217         case RENDERPATH_D3D10:
5218         case RENDERPATH_D3D11:
5219         case RENDERPATH_SOFT:
5220                 break;
5221         }
5222         GL_CullFace(r_refdef.view.cullface_back);
5223 }
5224
5225 /*
5226 ================
5227 R_RenderView_UpdateViewVectors
5228 ================
5229 */
5230 static void R_RenderView_UpdateViewVectors(void)
5231 {
5232         // break apart the view matrix into vectors for various purposes
5233         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5234         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5235         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5236         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5237         // make an inverted copy of the view matrix for tracking sprites
5238         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5239 }
5240
5241 void R_RenderScene(void);
5242 void R_RenderWaterPlanes(void);
5243
5244 static void R_Water_StartFrame(void)
5245 {
5246         int i;
5247         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5248         r_waterstate_waterplane_t *p;
5249
5250         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5251                 return;
5252
5253         switch(vid.renderpath)
5254         {
5255         case RENDERPATH_GL20:
5256         case RENDERPATH_D3D9:
5257         case RENDERPATH_D3D10:
5258         case RENDERPATH_D3D11:
5259         case RENDERPATH_SOFT:
5260         case RENDERPATH_GLES2:
5261                 break;
5262         case RENDERPATH_GL13:
5263         case RENDERPATH_GL11:
5264                 return;
5265         }
5266
5267         // set waterwidth and waterheight to the water resolution that will be
5268         // used (often less than the screen resolution for faster rendering)
5269         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5270         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5271
5272         // calculate desired texture sizes
5273         // can't use water if the card does not support the texture size
5274         if (!r_water.integer || r_showsurfaces.integer)
5275                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5276         else if (vid.support.arb_texture_non_power_of_two)
5277         {
5278                 texturewidth = waterwidth;
5279                 textureheight = waterheight;
5280                 camerawidth = waterwidth;
5281                 cameraheight = waterheight;
5282         }
5283         else
5284         {
5285                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5286                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5287                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5288                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5289         }
5290
5291         // allocate textures as needed
5292         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5293         {
5294                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5295                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5296                 {
5297                         if (p->texture_refraction)
5298                                 R_FreeTexture(p->texture_refraction);
5299                         p->texture_refraction = NULL;
5300                         if (p->texture_reflection)
5301                                 R_FreeTexture(p->texture_reflection);
5302                         p->texture_reflection = NULL;
5303                         if (p->texture_camera)
5304                                 R_FreeTexture(p->texture_camera);
5305                         p->texture_camera = NULL;
5306                 }
5307                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5308                 r_waterstate.texturewidth = texturewidth;
5309                 r_waterstate.textureheight = textureheight;
5310                 r_waterstate.camerawidth = camerawidth;
5311                 r_waterstate.cameraheight = cameraheight;
5312         }
5313
5314         if (r_waterstate.texturewidth)
5315         {
5316                 r_waterstate.enabled = true;
5317
5318                 // when doing a reduced render (HDR) we want to use a smaller area
5319                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5320                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5321
5322                 // set up variables that will be used in shader setup
5323                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5324                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5325                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5326                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5327         }
5328
5329         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5330         r_waterstate.numwaterplanes = 0;
5331 }
5332
5333 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5334 {
5335         int triangleindex, planeindex;
5336         const int *e;
5337         vec3_t vert[3];
5338         vec3_t normal;
5339         vec3_t center;
5340         mplane_t plane;
5341         r_waterstate_waterplane_t *p;
5342         texture_t *t = R_GetCurrentTexture(surface->texture);
5343
5344         // just use the first triangle with a valid normal for any decisions
5345         VectorClear(normal);
5346         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5347         {
5348                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5349                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5350                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5351                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5352                 if (VectorLength2(normal) >= 0.001)
5353                         break;
5354         }
5355
5356         VectorCopy(normal, plane.normal);
5357         VectorNormalize(plane.normal);
5358         plane.dist = DotProduct(vert[0], plane.normal);
5359         PlaneClassify(&plane);
5360         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5361         {
5362                 // skip backfaces (except if nocullface is set)
5363                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5364                         return;
5365                 VectorNegate(plane.normal, plane.normal);
5366                 plane.dist *= -1;
5367                 PlaneClassify(&plane);
5368         }
5369
5370
5371         // find a matching plane if there is one
5372         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5373                 if(p->camera_entity == t->camera_entity)
5374                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5375                                 break;
5376         if (planeindex >= r_waterstate.maxwaterplanes)
5377                 return; // nothing we can do, out of planes
5378
5379         // if this triangle does not fit any known plane rendered this frame, add one
5380         if (planeindex >= r_waterstate.numwaterplanes)
5381         {
5382                 // store the new plane
5383                 r_waterstate.numwaterplanes++;
5384                 p->plane = plane;
5385                 // clear materialflags and pvs
5386                 p->materialflags = 0;
5387                 p->pvsvalid = false;
5388                 p->camera_entity = t->camera_entity;
5389                 VectorCopy(surface->mins, p->mins);
5390                 VectorCopy(surface->maxs, p->maxs);
5391         }
5392         else
5393         {
5394                 // merge mins/maxs
5395                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5396                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5397                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5398                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5399                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5400                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5401         }
5402         // merge this surface's materialflags into the waterplane
5403         p->materialflags |= t->currentmaterialflags;
5404         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5405         {
5406                 // merge this surface's PVS into the waterplane
5407                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5408                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5409                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5410                 {
5411                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5412                         p->pvsvalid = true;
5413                 }
5414         }
5415 }
5416
5417 static void R_Water_ProcessPlanes(void)
5418 {
5419         int myscissor[4];
5420         r_refdef_view_t originalview;
5421         r_refdef_view_t myview;
5422         int planeindex;
5423         r_waterstate_waterplane_t *p;
5424         vec3_t visorigin;
5425
5426         originalview = r_refdef.view;
5427
5428         // make sure enough textures are allocated
5429         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5430         {
5431                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5432                 {
5433                         if (!p->texture_refraction)
5434                                 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);
5435                         if (!p->texture_refraction)
5436                                 goto error;
5437                 }
5438                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5439                 {
5440                         if (!p->texture_camera)
5441                                 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);
5442                         if (!p->texture_camera)
5443                                 goto error;
5444                 }
5445
5446                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5447                 {
5448                         if (!p->texture_reflection)
5449                                 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);
5450                         if (!p->texture_reflection)
5451                                 goto error;
5452                 }
5453         }
5454
5455         // render views
5456         r_refdef.view = originalview;
5457         r_refdef.view.showdebug = false;
5458         r_refdef.view.width = r_waterstate.waterwidth;
5459         r_refdef.view.height = r_waterstate.waterheight;
5460         r_refdef.view.useclipplane = true;
5461         myview = r_refdef.view;
5462         r_waterstate.renderingscene = true;
5463         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5464         {
5465                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5466                 {
5467                         r_refdef.view = myview;
5468                         if(r_water_scissormode.integer)
5469                         {
5470                                 R_SetupView(true);
5471                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5472                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5473                         }
5474
5475                         // render reflected scene and copy into texture
5476                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5477                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5478                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5479                         r_refdef.view.clipplane = p->plane;
5480
5481                         // reverse the cullface settings for this render
5482                         r_refdef.view.cullface_front = GL_FRONT;
5483                         r_refdef.view.cullface_back = GL_BACK;
5484                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5485                         {
5486                                 r_refdef.view.usecustompvs = true;
5487                                 if (p->pvsvalid)
5488                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5489                                 else
5490                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5491                         }
5492
5493                         R_ResetViewRendering3D();
5494                         R_ClearScreen(r_refdef.fogenabled);
5495                         if(r_water_scissormode.integer & 2)
5496                                 R_View_UpdateWithScissor(myscissor);
5497                         else
5498                                 R_View_Update();
5499                         if(r_water_scissormode.integer & 1)
5500                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5501                         R_RenderScene();
5502
5503                         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);
5504                 }
5505
5506                 // render the normal view scene and copy into texture
5507                 // (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)
5508                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5509                 {
5510                         r_refdef.view = myview;
5511                         if(r_water_scissormode.integer)
5512                         {
5513                                 R_SetupView(true);
5514                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5515                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5516                         }
5517
5518                         r_waterstate.renderingrefraction = true;
5519
5520                         r_refdef.view.clipplane = p->plane;
5521                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5522                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5523
5524                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5525                         {
5526                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5527                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5528                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5529                                 R_RenderView_UpdateViewVectors();
5530                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5531                                 {
5532                                         r_refdef.view.usecustompvs = true;
5533                                         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);
5534                                 }
5535                         }
5536
5537                         PlaneClassify(&r_refdef.view.clipplane);
5538
5539                         R_ResetViewRendering3D();
5540                         R_ClearScreen(r_refdef.fogenabled);
5541                         if(r_water_scissormode.integer & 2)
5542                                 R_View_UpdateWithScissor(myscissor);
5543                         else
5544                                 R_View_Update();
5545                         if(r_water_scissormode.integer & 1)
5546                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5547                         R_RenderScene();
5548
5549                         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);
5550                         r_waterstate.renderingrefraction = false;
5551                 }
5552                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5553                 {
5554                         r_refdef.view = myview;
5555
5556                         r_refdef.view.clipplane = p->plane;
5557                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5558                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5559
5560                         r_refdef.view.width = r_waterstate.camerawidth;
5561                         r_refdef.view.height = r_waterstate.cameraheight;
5562                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5563                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5564
5565                         if(p->camera_entity)
5566                         {
5567                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5568                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5569                         }
5570
5571                         // note: all of the view is used for displaying... so
5572                         // there is no use in scissoring
5573
5574                         // reverse the cullface settings for this render
5575                         r_refdef.view.cullface_front = GL_FRONT;
5576                         r_refdef.view.cullface_back = GL_BACK;
5577                         // also reverse the view matrix
5578                         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
5579                         R_RenderView_UpdateViewVectors();
5580                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5581                         {
5582                                 r_refdef.view.usecustompvs = true;
5583                                 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);
5584                         }
5585                         
5586                         // camera needs no clipplane
5587                         r_refdef.view.useclipplane = false;
5588
5589                         PlaneClassify(&r_refdef.view.clipplane);
5590
5591                         R_ResetViewRendering3D();
5592                         R_ClearScreen(r_refdef.fogenabled);
5593                         R_View_Update();
5594                         R_RenderScene();
5595
5596                         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);
5597                         r_waterstate.renderingrefraction = false;
5598                 }
5599
5600         }
5601         r_waterstate.renderingscene = false;
5602         r_refdef.view = originalview;
5603         R_ResetViewRendering3D();
5604         R_ClearScreen(r_refdef.fogenabled);
5605         R_View_Update();
5606         return;
5607 error:
5608         r_refdef.view = originalview;
5609         r_waterstate.renderingscene = false;
5610         Cvar_SetValueQuick(&r_water, 0);
5611         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5612         return;
5613 }
5614
5615 void R_Bloom_StartFrame(void)
5616 {
5617         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5618
5619         switch(vid.renderpath)
5620         {
5621         case RENDERPATH_GL20:
5622         case RENDERPATH_D3D9:
5623         case RENDERPATH_D3D10:
5624         case RENDERPATH_D3D11:
5625         case RENDERPATH_SOFT:
5626         case RENDERPATH_GLES2:
5627                 break;
5628         case RENDERPATH_GL13:
5629         case RENDERPATH_GL11:
5630                 return;
5631         }
5632
5633         // set bloomwidth and bloomheight to the bloom resolution that will be
5634         // used (often less than the screen resolution for faster rendering)
5635         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5636         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5637         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5638         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5639         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5640
5641         // calculate desired texture sizes
5642         if (vid.support.arb_texture_non_power_of_two)
5643         {
5644                 screentexturewidth = r_refdef.view.width;
5645                 screentextureheight = r_refdef.view.height;
5646                 bloomtexturewidth = r_bloomstate.bloomwidth;
5647                 bloomtextureheight = r_bloomstate.bloomheight;
5648         }
5649         else
5650         {
5651                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5652                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5653                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5654                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5655         }
5656
5657         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))
5658         {
5659                 Cvar_SetValueQuick(&r_hdr, 0);
5660                 Cvar_SetValueQuick(&r_bloom, 0);
5661                 Cvar_SetValueQuick(&r_motionblur, 0);
5662                 Cvar_SetValueQuick(&r_damageblur, 0);
5663         }
5664
5665         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)))
5666                 screentexturewidth = screentextureheight = 0;
5667         if (!r_hdr.integer && !r_bloom.integer)
5668                 bloomtexturewidth = bloomtextureheight = 0;
5669
5670         // allocate textures as needed
5671         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5672         {
5673                 if (r_bloomstate.texture_screen)
5674                         R_FreeTexture(r_bloomstate.texture_screen);
5675                 r_bloomstate.texture_screen = NULL;
5676                 r_bloomstate.screentexturewidth = screentexturewidth;
5677                 r_bloomstate.screentextureheight = screentextureheight;
5678                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5679                         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);
5680         }
5681         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5682         {
5683                 if (r_bloomstate.texture_bloom)
5684                         R_FreeTexture(r_bloomstate.texture_bloom);
5685                 r_bloomstate.texture_bloom = NULL;
5686                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5687                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5688                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5689                         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);
5690         }
5691
5692         // when doing a reduced render (HDR) we want to use a smaller area
5693         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5694         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5695         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5696         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5697         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5698
5699         // set up a texcoord array for the full resolution screen image
5700         // (we have to keep this around to copy back during final render)
5701         r_bloomstate.screentexcoord2f[0] = 0;
5702         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5703         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5704         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5705         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5706         r_bloomstate.screentexcoord2f[5] = 0;
5707         r_bloomstate.screentexcoord2f[6] = 0;
5708         r_bloomstate.screentexcoord2f[7] = 0;
5709
5710         // set up a texcoord array for the reduced resolution bloom image
5711         // (which will be additive blended over the screen image)
5712         r_bloomstate.bloomtexcoord2f[0] = 0;
5713         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5714         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5715         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5716         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5717         r_bloomstate.bloomtexcoord2f[5] = 0;
5718         r_bloomstate.bloomtexcoord2f[6] = 0;
5719         r_bloomstate.bloomtexcoord2f[7] = 0;
5720
5721         switch(vid.renderpath)
5722         {
5723         case RENDERPATH_GL11:
5724         case RENDERPATH_GL13:
5725         case RENDERPATH_GL20:
5726         case RENDERPATH_SOFT:
5727         case RENDERPATH_GLES2:
5728                 break;
5729         case RENDERPATH_D3D9:
5730         case RENDERPATH_D3D10:
5731         case RENDERPATH_D3D11:
5732                 {
5733                         int i;
5734                         for (i = 0;i < 4;i++)
5735                         {
5736                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5737                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5738                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5739                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5740                         }
5741                 }
5742                 break;
5743         }
5744
5745         if (r_hdr.integer || r_bloom.integer)
5746         {
5747                 r_bloomstate.enabled = true;
5748                 r_bloomstate.hdr = r_hdr.integer != 0;
5749         }
5750
5751         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);
5752 }
5753
5754 void R_Bloom_CopyBloomTexture(float colorscale)
5755 {
5756         r_refdef.stats.bloom++;
5757
5758         // scale down screen texture to the bloom texture size
5759         CHECKGLERROR
5760         R_SetViewport(&r_bloomstate.viewport);
5761         GL_BlendFunc(GL_ONE, GL_ZERO);
5762         GL_Color(colorscale, colorscale, colorscale, 1);
5763         // 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...
5764         switch(vid.renderpath)
5765         {
5766         case RENDERPATH_GL11:
5767         case RENDERPATH_GL13:
5768         case RENDERPATH_GL20:
5769         case RENDERPATH_SOFT:
5770         case RENDERPATH_GLES2:
5771                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5772                 break;
5773         case RENDERPATH_D3D9:
5774         case RENDERPATH_D3D10:
5775         case RENDERPATH_D3D11:
5776                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5777                 break;
5778         }
5779         // TODO: do boxfilter scale-down in shader?
5780         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5781         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5782         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5783
5784         // we now have a bloom image in the framebuffer
5785         // copy it into the bloom image texture for later processing
5786         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);
5787         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5788 }
5789
5790 void R_Bloom_CopyHDRTexture(void)
5791 {
5792         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);
5793         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5794 }
5795
5796 void R_Bloom_MakeTexture(void)
5797 {
5798         int x, range, dir;
5799         float xoffset, yoffset, r, brighten;
5800
5801         r_refdef.stats.bloom++;
5802
5803         R_ResetViewRendering2D();
5804
5805         // we have a bloom image in the framebuffer
5806         CHECKGLERROR
5807         R_SetViewport(&r_bloomstate.viewport);
5808
5809         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5810         {
5811                 x *= 2;
5812                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5813                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5814                 GL_Color(r,r,r,1);
5815                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5816                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5817                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5818                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5819
5820                 // copy the vertically blurred bloom view to a texture
5821                 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);
5822                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5823         }
5824
5825         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5826         brighten = r_bloom_brighten.value;
5827         if (r_hdr.integer)
5828                 brighten *= r_hdr_range.value;
5829         brighten = sqrt(brighten);
5830         if(range >= 1)
5831                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5832         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5833
5834         for (dir = 0;dir < 2;dir++)
5835         {
5836                 // blend on at multiple vertical offsets to achieve a vertical blur
5837                 // TODO: do offset blends using GLSL
5838                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5839                 GL_BlendFunc(GL_ONE, GL_ZERO);
5840                 for (x = -range;x <= range;x++)
5841                 {
5842                         if (!dir){xoffset = 0;yoffset = x;}
5843                         else {xoffset = x;yoffset = 0;}
5844                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5845                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5846                         // compute a texcoord array with the specified x and y offset
5847                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5848                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5849                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5850                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5851                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5852                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5853                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5854                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5855                         // this r value looks like a 'dot' particle, fading sharply to
5856                         // black at the edges
5857                         // (probably not realistic but looks good enough)
5858                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5859                         //r = brighten/(range*2+1);
5860                         r = brighten / (range * 2 + 1);
5861                         if(range >= 1)
5862                                 r *= (1 - x*x/(float)(range*range));
5863                         GL_Color(r, r, r, 1);
5864                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5865                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5866                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5867                         GL_BlendFunc(GL_ONE, GL_ONE);
5868                 }
5869
5870                 // copy the vertically blurred bloom view to a texture
5871                 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);
5872                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5873         }
5874 }
5875
5876 void R_HDR_RenderBloomTexture(void)
5877 {
5878         int oldwidth, oldheight;
5879         float oldcolorscale;
5880         qboolean oldwaterstate;
5881
5882         oldwaterstate = r_waterstate.enabled;
5883         oldcolorscale = r_refdef.view.colorscale;
5884         oldwidth = r_refdef.view.width;
5885         oldheight = r_refdef.view.height;
5886         r_refdef.view.width = r_bloomstate.bloomwidth;
5887         r_refdef.view.height = r_bloomstate.bloomheight;
5888
5889         if(r_hdr.integer < 2)
5890                 r_waterstate.enabled = false;
5891
5892         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5893         // TODO: add exposure compensation features
5894         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5895
5896         r_refdef.view.showdebug = false;
5897         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5898
5899         R_ResetViewRendering3D();
5900
5901         R_ClearScreen(r_refdef.fogenabled);
5902         if (r_timereport_active)
5903                 R_TimeReport("HDRclear");
5904
5905         R_View_Update();
5906         if (r_timereport_active)
5907                 R_TimeReport("visibility");
5908
5909         // only do secondary renders with HDR if r_hdr is 2 or higher
5910         r_waterstate.numwaterplanes = 0;
5911         if (r_waterstate.enabled)
5912                 R_RenderWaterPlanes();
5913
5914         r_refdef.view.showdebug = true;
5915         R_RenderScene();
5916         r_waterstate.numwaterplanes = 0;
5917
5918         R_ResetViewRendering2D();
5919
5920         R_Bloom_CopyHDRTexture();
5921         R_Bloom_MakeTexture();
5922
5923         // restore the view settings
5924         r_waterstate.enabled = oldwaterstate;
5925         r_refdef.view.width = oldwidth;
5926         r_refdef.view.height = oldheight;
5927         r_refdef.view.colorscale = oldcolorscale;
5928
5929         R_ResetViewRendering3D();
5930
5931         R_ClearScreen(r_refdef.fogenabled);
5932         if (r_timereport_active)
5933                 R_TimeReport("viewclear");
5934 }
5935
5936 static void R_BlendView(void)
5937 {
5938         unsigned int permutation;
5939         float uservecs[4][4];
5940
5941         switch (vid.renderpath)
5942         {
5943         case RENDERPATH_GL20:
5944         case RENDERPATH_D3D9:
5945         case RENDERPATH_D3D10:
5946         case RENDERPATH_D3D11:
5947         case RENDERPATH_SOFT:
5948         case RENDERPATH_GLES2:
5949                 permutation =
5950                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5951                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5952                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5953                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5954                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5955
5956                 if (r_bloomstate.texture_screen)
5957                 {
5958                         // make sure the buffer is available
5959                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5960
5961                         R_ResetViewRendering2D();
5962
5963                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5964                         {
5965                                 // declare variables
5966                                 float speed;
5967                                 static float avgspeed;
5968
5969                                 speed = VectorLength(cl.movement_velocity);
5970
5971                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5972                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5973
5974                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5975                                 speed = bound(0, speed, 1);
5976                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5977
5978                                 // calculate values into a standard alpha
5979                                 cl.motionbluralpha = 1 - exp(-
5980                                                 (
5981                                                  (r_motionblur.value * speed / 80)
5982                                                  +
5983                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5984                                                 )
5985                                                 /
5986                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
5987                                            );
5988
5989                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5990                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5991                                 // apply the blur
5992                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
5993                                 {
5994                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5995                                         GL_Color(1, 1, 1, cl.motionbluralpha);
5996                                         switch(vid.renderpath)
5997                                         {
5998                                         case RENDERPATH_GL11:
5999                                         case RENDERPATH_GL13:
6000                                         case RENDERPATH_GL20:
6001                                         case RENDERPATH_SOFT:
6002                                         case RENDERPATH_GLES2:
6003                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6004                                                 break;
6005                                         case RENDERPATH_D3D9:
6006                                         case RENDERPATH_D3D10:
6007                                         case RENDERPATH_D3D11:
6008                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6009                                                 break;
6010                                         }
6011                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6012                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6013                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6014                                 }
6015                         }
6016
6017                         // copy view into the screen texture
6018                         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);
6019                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6020                 }
6021                 else if (!r_bloomstate.texture_bloom)
6022                 {
6023                         // we may still have to do view tint...
6024                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6025                         {
6026                                 // apply a color tint to the whole view
6027                                 R_ResetViewRendering2D();
6028                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6029                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6030                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6031                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6032                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6033                         }
6034                         break; // no screen processing, no bloom, skip it
6035                 }
6036
6037                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6038                 {
6039                         // render simple bloom effect
6040                         // copy the screen and shrink it and darken it for the bloom process
6041                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6042                         // make the bloom texture
6043                         R_Bloom_MakeTexture();
6044                 }
6045
6046 #if _MSC_VER >= 1400
6047 #define sscanf sscanf_s
6048 #endif
6049                 memset(uservecs, 0, sizeof(uservecs));
6050                 if (r_glsl_postprocess_uservec1_enable.integer)
6051                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6052                 if (r_glsl_postprocess_uservec2_enable.integer)
6053                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6054                 if (r_glsl_postprocess_uservec3_enable.integer)
6055                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6056                 if (r_glsl_postprocess_uservec4_enable.integer)
6057                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6058
6059                 R_ResetViewRendering2D();
6060                 GL_Color(1, 1, 1, 1);
6061                 GL_BlendFunc(GL_ONE, GL_ZERO);
6062
6063                 switch(vid.renderpath)
6064                 {
6065                 case RENDERPATH_GL20:
6066                 case RENDERPATH_GLES2:
6067                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6068                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6069                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6070                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6071                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6072                         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]);
6073                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6074                         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]);
6075                         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]);
6076                         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]);
6077                         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]);
6078                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6079                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6080                         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);
6081                         break;
6082                 case RENDERPATH_D3D9:
6083 #ifdef SUPPORTD3D
6084                         // 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...
6085                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6086                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6087                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6088                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6089                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6090                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6091                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6092                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6093                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6094                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6095                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6096                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6097                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6098                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6099 #endif
6100                         break;
6101                 case RENDERPATH_D3D10:
6102                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6103                         break;
6104                 case RENDERPATH_D3D11:
6105                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6106                         break;
6107                 case RENDERPATH_SOFT:
6108                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6109                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6110                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6111                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6112                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6113                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6114                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6115                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6116                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6117                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6118                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6119                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6120                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6121                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6122                         break;
6123                 default:
6124                         break;
6125                 }
6126                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6127                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6128                 break;
6129         case RENDERPATH_GL13:
6130         case RENDERPATH_GL11:
6131                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6132                 {
6133                         // apply a color tint to the whole view
6134                         R_ResetViewRendering2D();
6135                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6136                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6137                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6138                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6139                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6140                 }
6141                 break;
6142         }
6143 }
6144
6145 matrix4x4_t r_waterscrollmatrix;
6146
6147 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6148 {
6149         if (r_refdef.fog_density)
6150         {
6151                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6152                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6153                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6154
6155                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6156                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6157                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6158                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6159
6160                 {
6161                         vec3_t fogvec;
6162                         VectorCopy(r_refdef.fogcolor, fogvec);
6163                         //   color.rgb *= ContrastBoost * SceneBrightness;
6164                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6165                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6166                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6167                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6168                 }
6169         }
6170 }
6171
6172 void R_UpdateVariables(void)
6173 {
6174         R_Textures_Frame();
6175
6176         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6177
6178         r_refdef.farclip = r_farclip_base.value;
6179         if (r_refdef.scene.worldmodel)
6180                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6181         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6182
6183         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6184                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6185         r_refdef.polygonfactor = 0;
6186         r_refdef.polygonoffset = 0;
6187         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6188         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6189
6190         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6191         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6192         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6193         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6194         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6195         if (FAKELIGHT_ENABLED)
6196         {
6197                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6198         }
6199         if (r_showsurfaces.integer)
6200         {
6201                 r_refdef.scene.rtworld = false;
6202                 r_refdef.scene.rtworldshadows = false;
6203                 r_refdef.scene.rtdlight = false;
6204                 r_refdef.scene.rtdlightshadows = false;
6205                 r_refdef.lightmapintensity = 0;
6206         }
6207
6208         if (gamemode == GAME_NEHAHRA)
6209         {
6210                 if (gl_fogenable.integer)
6211                 {
6212                         r_refdef.oldgl_fogenable = true;
6213                         r_refdef.fog_density = gl_fogdensity.value;
6214                         r_refdef.fog_red = gl_fogred.value;
6215                         r_refdef.fog_green = gl_foggreen.value;
6216                         r_refdef.fog_blue = gl_fogblue.value;
6217                         r_refdef.fog_alpha = 1;
6218                         r_refdef.fog_start = 0;
6219                         r_refdef.fog_end = gl_skyclip.value;
6220                         r_refdef.fog_height = 1<<30;
6221                         r_refdef.fog_fadedepth = 128;
6222                 }
6223                 else if (r_refdef.oldgl_fogenable)
6224                 {
6225                         r_refdef.oldgl_fogenable = false;
6226                         r_refdef.fog_density = 0;
6227                         r_refdef.fog_red = 0;
6228                         r_refdef.fog_green = 0;
6229                         r_refdef.fog_blue = 0;
6230                         r_refdef.fog_alpha = 0;
6231                         r_refdef.fog_start = 0;
6232                         r_refdef.fog_end = 0;
6233                         r_refdef.fog_height = 1<<30;
6234                         r_refdef.fog_fadedepth = 128;
6235                 }
6236         }
6237
6238         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6239         r_refdef.fog_start = max(0, r_refdef.fog_start);
6240         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6241
6242         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6243
6244         if (r_refdef.fog_density && r_drawfog.integer)
6245         {
6246                 r_refdef.fogenabled = true;
6247                 // this is the point where the fog reaches 0.9986 alpha, which we
6248                 // consider a good enough cutoff point for the texture
6249                 // (0.9986 * 256 == 255.6)
6250                 if (r_fog_exp2.integer)
6251                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6252                 else
6253                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6254                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6255                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6256                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6257                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6258                         R_BuildFogHeightTexture();
6259                 // fog color was already set
6260                 // update the fog texture
6261                 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)
6262                         R_BuildFogTexture();
6263                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6264                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6265         }
6266         else
6267                 r_refdef.fogenabled = false;
6268
6269         switch(vid.renderpath)
6270         {
6271         case RENDERPATH_GL20:
6272         case RENDERPATH_D3D9:
6273         case RENDERPATH_D3D10:
6274         case RENDERPATH_D3D11:
6275         case RENDERPATH_SOFT:
6276         case RENDERPATH_GLES2:
6277                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6278                 {
6279                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6280                         {
6281                                 // build GLSL gamma texture
6282 #define RAMPWIDTH 256
6283                                 unsigned short ramp[RAMPWIDTH * 3];
6284                                 unsigned char rampbgr[RAMPWIDTH][4];
6285                                 int i;
6286
6287                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6288
6289                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6290                                 for(i = 0; i < RAMPWIDTH; ++i)
6291                                 {
6292                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6293                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6294                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6295                                         rampbgr[i][3] = 0;
6296                                 }
6297                                 if (r_texture_gammaramps)
6298                                 {
6299                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6300                                 }
6301                                 else
6302                                 {
6303                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6304                                 }
6305                         }
6306                 }
6307                 else
6308                 {
6309                         // remove GLSL gamma texture
6310                 }
6311                 break;
6312         case RENDERPATH_GL13:
6313         case RENDERPATH_GL11:
6314                 break;
6315         }
6316 }
6317
6318 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6319 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6320 /*
6321 ================
6322 R_SelectScene
6323 ================
6324 */
6325 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6326         if( scenetype != r_currentscenetype ) {
6327                 // store the old scenetype
6328                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6329                 r_currentscenetype = scenetype;
6330                 // move in the new scene
6331                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6332         }
6333 }
6334
6335 /*
6336 ================
6337 R_GetScenePointer
6338 ================
6339 */
6340 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6341 {
6342         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6343         if( scenetype == r_currentscenetype ) {
6344                 return &r_refdef.scene;
6345         } else {
6346                 return &r_scenes_store[ scenetype ];
6347         }
6348 }
6349
6350 /*
6351 ================
6352 R_RenderView
6353 ================
6354 */
6355 int dpsoftrast_test;
6356 void R_RenderView(void)
6357 {
6358         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6359
6360         dpsoftrast_test = r_test.integer;
6361
6362         if (r_timereport_active)
6363                 R_TimeReport("start");
6364         r_textureframe++; // used only by R_GetCurrentTexture
6365         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6366
6367         if(R_CompileShader_CheckStaticParms())
6368                 R_GLSL_Restart_f();
6369
6370         if (!r_drawentities.integer)
6371                 r_refdef.scene.numentities = 0;
6372
6373         R_AnimCache_ClearCache();
6374         R_FrameData_NewFrame();
6375
6376         /* adjust for stereo display */
6377         if(R_Stereo_Active())
6378         {
6379                 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);
6380                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6381         }
6382
6383         if (r_refdef.view.isoverlay)
6384         {
6385                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6386                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6387                 R_TimeReport("depthclear");
6388
6389                 r_refdef.view.showdebug = false;
6390
6391                 r_waterstate.enabled = false;
6392                 r_waterstate.numwaterplanes = 0;
6393
6394                 R_RenderScene();
6395
6396                 r_refdef.view.matrix = originalmatrix;
6397
6398                 CHECKGLERROR
6399                 return;
6400         }
6401
6402         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6403         {
6404                 r_refdef.view.matrix = originalmatrix;
6405                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6406         }
6407
6408         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6409
6410         R_RenderView_UpdateViewVectors();
6411
6412         R_Shadow_UpdateWorldLightSelection();
6413
6414         R_Bloom_StartFrame();
6415         R_Water_StartFrame();
6416
6417         CHECKGLERROR
6418         if (r_timereport_active)
6419                 R_TimeReport("viewsetup");
6420
6421         R_ResetViewRendering3D();
6422
6423         if (r_refdef.view.clear || r_refdef.fogenabled)
6424         {
6425                 R_ClearScreen(r_refdef.fogenabled);
6426                 if (r_timereport_active)
6427                         R_TimeReport("viewclear");
6428         }
6429         r_refdef.view.clear = true;
6430
6431         // this produces a bloom texture to be used in R_BlendView() later
6432         if (r_hdr.integer && r_bloomstate.bloomwidth)
6433         {
6434                 R_HDR_RenderBloomTexture();
6435                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6436                 r_textureframe++; // used only by R_GetCurrentTexture
6437         }
6438
6439         r_refdef.view.showdebug = true;
6440
6441         R_View_Update();
6442         if (r_timereport_active)
6443                 R_TimeReport("visibility");
6444
6445         r_waterstate.numwaterplanes = 0;
6446         if (r_waterstate.enabled)
6447                 R_RenderWaterPlanes();
6448
6449         R_RenderScene();
6450         r_waterstate.numwaterplanes = 0;
6451
6452         R_BlendView();
6453         if (r_timereport_active)
6454                 R_TimeReport("blendview");
6455
6456         GL_Scissor(0, 0, vid.width, vid.height);
6457         GL_ScissorTest(false);
6458
6459         r_refdef.view.matrix = originalmatrix;
6460
6461         CHECKGLERROR
6462 }
6463
6464 void R_RenderWaterPlanes(void)
6465 {
6466         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6467         {
6468                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6469                 if (r_timereport_active)
6470                         R_TimeReport("waterworld");
6471         }
6472
6473         // don't let sound skip if going slow
6474         if (r_refdef.scene.extraupdate)
6475                 S_ExtraUpdate ();
6476
6477         R_DrawModelsAddWaterPlanes();
6478         if (r_timereport_active)
6479                 R_TimeReport("watermodels");
6480
6481         if (r_waterstate.numwaterplanes)
6482         {
6483                 R_Water_ProcessPlanes();
6484                 if (r_timereport_active)
6485                         R_TimeReport("waterscenes");
6486         }
6487 }
6488
6489 extern void R_DrawLightningBeams (void);
6490 extern void VM_CL_AddPolygonsToMeshQueue (void);
6491 extern void R_DrawPortals (void);
6492 extern cvar_t cl_locs_show;
6493 static void R_DrawLocs(void);
6494 static void R_DrawEntityBBoxes(void);
6495 static void R_DrawModelDecals(void);
6496 extern void R_DrawModelShadows(void);
6497 extern void R_DrawModelShadowMaps(void);
6498 extern cvar_t cl_decals_newsystem;
6499 extern qboolean r_shadow_usingdeferredprepass;
6500 void R_RenderScene(void)
6501 {
6502         qboolean shadowmapping = false;
6503
6504         if (r_timereport_active)
6505                 R_TimeReport("beginscene");
6506
6507         r_refdef.stats.renders++;
6508
6509         R_UpdateFogColor();
6510
6511         // don't let sound skip if going slow
6512         if (r_refdef.scene.extraupdate)
6513                 S_ExtraUpdate ();
6514
6515         R_MeshQueue_BeginScene();
6516
6517         R_SkyStartFrame();
6518
6519         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);
6520
6521         if (r_timereport_active)
6522                 R_TimeReport("skystartframe");
6523
6524         if (cl.csqc_vidvars.drawworld)
6525         {
6526                 // don't let sound skip if going slow
6527                 if (r_refdef.scene.extraupdate)
6528                         S_ExtraUpdate ();
6529
6530                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6531                 {
6532                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6533                         if (r_timereport_active)
6534                                 R_TimeReport("worldsky");
6535                 }
6536
6537                 if (R_DrawBrushModelsSky() && r_timereport_active)
6538                         R_TimeReport("bmodelsky");
6539
6540                 if (skyrendermasked && skyrenderlater)
6541                 {
6542                         // we have to force off the water clipping plane while rendering sky
6543                         R_SetupView(false);
6544                         R_Sky();
6545                         R_SetupView(true);
6546                         if (r_timereport_active)
6547                                 R_TimeReport("sky");
6548                 }
6549         }
6550
6551         R_AnimCache_CacheVisibleEntities();
6552         if (r_timereport_active)
6553                 R_TimeReport("animation");
6554
6555         R_Shadow_PrepareLights();
6556         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6557                 R_Shadow_PrepareModelShadows();
6558         if (r_timereport_active)
6559                 R_TimeReport("preparelights");
6560
6561         if (R_Shadow_ShadowMappingEnabled())
6562                 shadowmapping = true;
6563
6564         if (r_shadow_usingdeferredprepass)
6565                 R_Shadow_DrawPrepass();
6566
6567         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6568         {
6569                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6570                 if (r_timereport_active)
6571                         R_TimeReport("worlddepth");
6572         }
6573         if (r_depthfirst.integer >= 2)
6574         {
6575                 R_DrawModelsDepth();
6576                 if (r_timereport_active)
6577                         R_TimeReport("modeldepth");
6578         }
6579
6580         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6581         {
6582                 R_DrawModelShadowMaps();
6583                 R_ResetViewRendering3D();
6584                 // don't let sound skip if going slow
6585                 if (r_refdef.scene.extraupdate)
6586                         S_ExtraUpdate ();
6587         }
6588
6589         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6590         {
6591                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6592                 if (r_timereport_active)
6593                         R_TimeReport("world");
6594         }
6595
6596         // don't let sound skip if going slow
6597         if (r_refdef.scene.extraupdate)
6598                 S_ExtraUpdate ();
6599
6600         R_DrawModels();
6601         if (r_timereport_active)
6602                 R_TimeReport("models");
6603
6604         // don't let sound skip if going slow
6605         if (r_refdef.scene.extraupdate)
6606                 S_ExtraUpdate ();
6607
6608         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6609         {
6610                 R_DrawModelShadows();
6611                 R_ResetViewRendering3D();
6612                 // don't let sound skip if going slow
6613                 if (r_refdef.scene.extraupdate)
6614                         S_ExtraUpdate ();
6615         }
6616
6617         if (!r_shadow_usingdeferredprepass)
6618         {
6619                 R_Shadow_DrawLights();
6620                 if (r_timereport_active)
6621                         R_TimeReport("rtlights");
6622         }
6623
6624         // don't let sound skip if going slow
6625         if (r_refdef.scene.extraupdate)
6626                 S_ExtraUpdate ();
6627
6628         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6629         {
6630                 R_DrawModelShadows();
6631                 R_ResetViewRendering3D();
6632                 // don't let sound skip if going slow
6633                 if (r_refdef.scene.extraupdate)
6634                         S_ExtraUpdate ();
6635         }
6636
6637         if (cl.csqc_vidvars.drawworld)
6638         {
6639                 if (cl_decals_newsystem.integer)
6640                 {
6641                         R_DrawModelDecals();
6642                         if (r_timereport_active)
6643                                 R_TimeReport("modeldecals");
6644                 }
6645                 else
6646                 {
6647                         R_DrawDecals();
6648                         if (r_timereport_active)
6649                                 R_TimeReport("decals");
6650                 }
6651
6652                 R_DrawParticles();
6653                 if (r_timereport_active)
6654                         R_TimeReport("particles");
6655
6656                 R_DrawExplosions();
6657                 if (r_timereport_active)
6658                         R_TimeReport("explosions");
6659
6660                 R_DrawLightningBeams();
6661                 if (r_timereport_active)
6662                         R_TimeReport("lightning");
6663         }
6664
6665         VM_CL_AddPolygonsToMeshQueue();
6666
6667         if (r_refdef.view.showdebug)
6668         {
6669                 if (cl_locs_show.integer)
6670                 {
6671                         R_DrawLocs();
6672                         if (r_timereport_active)
6673                                 R_TimeReport("showlocs");
6674                 }
6675
6676                 if (r_drawportals.integer)
6677                 {
6678                         R_DrawPortals();
6679                         if (r_timereport_active)
6680                                 R_TimeReport("portals");
6681                 }
6682
6683                 if (r_showbboxes.value > 0)
6684                 {
6685                         R_DrawEntityBBoxes();
6686                         if (r_timereport_active)
6687                                 R_TimeReport("bboxes");
6688                 }
6689         }
6690
6691         R_MeshQueue_RenderTransparent();
6692         if (r_timereport_active)
6693                 R_TimeReport("drawtrans");
6694
6695         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))
6696         {
6697                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6698                 if (r_timereport_active)
6699                         R_TimeReport("worlddebug");
6700                 R_DrawModelsDebug();
6701                 if (r_timereport_active)
6702                         R_TimeReport("modeldebug");
6703         }
6704
6705         if (cl.csqc_vidvars.drawworld)
6706         {
6707                 R_Shadow_DrawCoronas();
6708                 if (r_timereport_active)
6709                         R_TimeReport("coronas");
6710         }
6711
6712 #if 0
6713         {
6714                 GL_DepthTest(false);
6715                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6716                 GL_Color(1, 1, 1, 1);
6717                 qglBegin(GL_POLYGON);
6718                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6719                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6720                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6721                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6722                 qglEnd();
6723                 qglBegin(GL_POLYGON);
6724                 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]);
6725                 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]);
6726                 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]);
6727                 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]);
6728                 qglEnd();
6729                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6730         }
6731 #endif
6732
6733         // don't let sound skip if going slow
6734         if (r_refdef.scene.extraupdate)
6735                 S_ExtraUpdate ();
6736
6737         R_ResetViewRendering2D();
6738 }
6739
6740 static const unsigned short bboxelements[36] =
6741 {
6742         5, 1, 3, 5, 3, 7,
6743         6, 2, 0, 6, 0, 4,
6744         7, 3, 2, 7, 2, 6,
6745         4, 0, 1, 4, 1, 5,
6746         4, 5, 7, 4, 7, 6,
6747         1, 0, 2, 1, 2, 3,
6748 };
6749
6750 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6751 {
6752         int i;
6753         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6754
6755         RSurf_ActiveWorldEntity();
6756
6757         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6758         GL_DepthMask(false);
6759         GL_DepthRange(0, 1);
6760         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6761 //      R_Mesh_ResetTextureState();
6762
6763         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6764         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6765         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6766         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6767         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6768         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6769         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6770         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6771         R_FillColors(color4f, 8, cr, cg, cb, ca);
6772         if (r_refdef.fogenabled)
6773         {
6774                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6775                 {
6776                         f1 = RSurf_FogVertex(v);
6777                         f2 = 1 - f1;
6778                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6779                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6780                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6781                 }
6782         }
6783         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6784         R_Mesh_ResetTextureState();
6785         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6786         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6787 }
6788
6789 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6790 {
6791         int i;
6792         float color[4];
6793         prvm_edict_t *edict;
6794         prvm_prog_t *prog_save = prog;
6795
6796         // this function draws bounding boxes of server entities
6797         if (!sv.active)
6798                 return;
6799
6800         GL_CullFace(GL_NONE);
6801         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6802
6803         prog = 0;
6804         SV_VM_Begin();
6805         for (i = 0;i < numsurfaces;i++)
6806         {
6807                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6808                 switch ((int)edict->fields.server->solid)
6809                 {
6810                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6811                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6812                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6813                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6814                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6815                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6816                 }
6817                 color[3] *= r_showbboxes.value;
6818                 color[3] = bound(0, color[3], 1);
6819                 GL_DepthTest(!r_showdisabledepthtest.integer);
6820                 GL_CullFace(r_refdef.view.cullface_front);
6821                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6822         }
6823         SV_VM_End();
6824         prog = prog_save;
6825 }
6826
6827 static void R_DrawEntityBBoxes(void)
6828 {
6829         int i;
6830         prvm_edict_t *edict;
6831         vec3_t center;
6832         prvm_prog_t *prog_save = prog;
6833
6834         // this function draws bounding boxes of server entities
6835         if (!sv.active)
6836                 return;
6837
6838         prog = 0;
6839         SV_VM_Begin();
6840         for (i = 0;i < prog->num_edicts;i++)
6841         {
6842                 edict = PRVM_EDICT_NUM(i);
6843                 if (edict->priv.server->free)
6844                         continue;
6845                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6846                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6847                         continue;
6848                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6849                         continue;
6850                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6851                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6852         }
6853         SV_VM_End();
6854         prog = prog_save;
6855 }
6856
6857 static const int nomodelelement3i[24] =
6858 {
6859         5, 2, 0,
6860         5, 1, 2,
6861         5, 0, 3,
6862         5, 3, 1,
6863         0, 2, 4,
6864         2, 1, 4,
6865         3, 0, 4,
6866         1, 3, 4
6867 };
6868
6869 static const unsigned short nomodelelement3s[24] =
6870 {
6871         5, 2, 0,
6872         5, 1, 2,
6873         5, 0, 3,
6874         5, 3, 1,
6875         0, 2, 4,
6876         2, 1, 4,
6877         3, 0, 4,
6878         1, 3, 4
6879 };
6880
6881 static const float nomodelvertex3f[6*3] =
6882 {
6883         -16,   0,   0,
6884          16,   0,   0,
6885           0, -16,   0,
6886           0,  16,   0,
6887           0,   0, -16,
6888           0,   0,  16
6889 };
6890
6891 static const float nomodelcolor4f[6*4] =
6892 {
6893         0.0f, 0.0f, 0.5f, 1.0f,
6894         0.0f, 0.0f, 0.5f, 1.0f,
6895         0.0f, 0.5f, 0.0f, 1.0f,
6896         0.0f, 0.5f, 0.0f, 1.0f,
6897         0.5f, 0.0f, 0.0f, 1.0f,
6898         0.5f, 0.0f, 0.0f, 1.0f
6899 };
6900
6901 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6902 {
6903         int i;
6904         float f1, f2, *c;
6905         float color4f[6*4];
6906
6907         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);
6908
6909         // this is only called once per entity so numsurfaces is always 1, and
6910         // surfacelist is always {0}, so this code does not handle batches
6911
6912         if (rsurface.ent_flags & RENDER_ADDITIVE)
6913         {
6914                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6915                 GL_DepthMask(false);
6916         }
6917         else if (rsurface.colormod[3] < 1)
6918         {
6919                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6920                 GL_DepthMask(false);
6921         }
6922         else
6923         {
6924                 GL_BlendFunc(GL_ONE, GL_ZERO);
6925                 GL_DepthMask(true);
6926         }
6927         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6928         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6929         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6930         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6931         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6932         for (i = 0, c = color4f;i < 6;i++, c += 4)
6933         {
6934                 c[0] *= rsurface.colormod[0];
6935                 c[1] *= rsurface.colormod[1];
6936                 c[2] *= rsurface.colormod[2];
6937                 c[3] *= rsurface.colormod[3];
6938         }
6939         if (r_refdef.fogenabled)
6940         {
6941                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6942                 {
6943                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6944                         f2 = 1 - f1;
6945                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6946                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6947                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6948                 }
6949         }
6950 //      R_Mesh_ResetTextureState();
6951         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6952         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6953         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6954 }
6955
6956 void R_DrawNoModel(entity_render_t *ent)
6957 {
6958         vec3_t org;
6959         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6960         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6961                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6962         else
6963                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6964 }
6965
6966 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6967 {
6968         vec3_t right1, right2, diff, normal;
6969
6970         VectorSubtract (org2, org1, normal);
6971
6972         // calculate 'right' vector for start
6973         VectorSubtract (r_refdef.view.origin, org1, diff);
6974         CrossProduct (normal, diff, right1);
6975         VectorNormalize (right1);
6976
6977         // calculate 'right' vector for end
6978         VectorSubtract (r_refdef.view.origin, org2, diff);
6979         CrossProduct (normal, diff, right2);
6980         VectorNormalize (right2);
6981
6982         vert[ 0] = org1[0] + width * right1[0];
6983         vert[ 1] = org1[1] + width * right1[1];
6984         vert[ 2] = org1[2] + width * right1[2];
6985         vert[ 3] = org1[0] - width * right1[0];
6986         vert[ 4] = org1[1] - width * right1[1];
6987         vert[ 5] = org1[2] - width * right1[2];
6988         vert[ 6] = org2[0] - width * right2[0];
6989         vert[ 7] = org2[1] - width * right2[1];
6990         vert[ 8] = org2[2] - width * right2[2];
6991         vert[ 9] = org2[0] + width * right2[0];
6992         vert[10] = org2[1] + width * right2[1];
6993         vert[11] = org2[2] + width * right2[2];
6994 }
6995
6996 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)
6997 {
6998         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6999         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7000         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7001         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7002         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7003         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7004         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7005         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7006         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7007         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7008         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7009         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7010 }
7011
7012 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7013 {
7014         int i;
7015         float *vertex3f;
7016         float v[3];
7017         VectorSet(v, x, y, z);
7018         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7019                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7020                         break;
7021         if (i == mesh->numvertices)
7022         {
7023                 if (mesh->numvertices < mesh->maxvertices)
7024                 {
7025                         VectorCopy(v, vertex3f);
7026                         mesh->numvertices++;
7027                 }
7028                 return mesh->numvertices;
7029         }
7030         else
7031                 return i;
7032 }
7033
7034 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7035 {
7036         int i;
7037         int *e, element[3];
7038         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7039         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7040         e = mesh->element3i + mesh->numtriangles * 3;
7041         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7042         {
7043                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7044                 if (mesh->numtriangles < mesh->maxtriangles)
7045                 {
7046                         *e++ = element[0];
7047                         *e++ = element[1];
7048                         *e++ = element[2];
7049                         mesh->numtriangles++;
7050                 }
7051                 element[1] = element[2];
7052         }
7053 }
7054
7055 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7056 {
7057         int i;
7058         int *e, element[3];
7059         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7060         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7061         e = mesh->element3i + mesh->numtriangles * 3;
7062         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7063         {
7064                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7065                 if (mesh->numtriangles < mesh->maxtriangles)
7066                 {
7067                         *e++ = element[0];
7068                         *e++ = element[1];
7069                         *e++ = element[2];
7070                         mesh->numtriangles++;
7071                 }
7072                 element[1] = element[2];
7073         }
7074 }
7075
7076 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7077 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7078 {
7079         int planenum, planenum2;
7080         int w;
7081         int tempnumpoints;
7082         mplane_t *plane, *plane2;
7083         double maxdist;
7084         double temppoints[2][256*3];
7085         // figure out how large a bounding box we need to properly compute this brush
7086         maxdist = 0;
7087         for (w = 0;w < numplanes;w++)
7088                 maxdist = max(maxdist, fabs(planes[w].dist));
7089         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7090         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7091         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7092         {
7093                 w = 0;
7094                 tempnumpoints = 4;
7095                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7096                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7097                 {
7098                         if (planenum2 == planenum)
7099                                 continue;
7100                         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);
7101                         w = !w;
7102                 }
7103                 if (tempnumpoints < 3)
7104                         continue;
7105                 // generate elements forming a triangle fan for this polygon
7106                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7107         }
7108 }
7109
7110 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)
7111 {
7112         texturelayer_t *layer;
7113         layer = t->currentlayers + t->currentnumlayers++;
7114         layer->type = type;
7115         layer->depthmask = depthmask;
7116         layer->blendfunc1 = blendfunc1;
7117         layer->blendfunc2 = blendfunc2;
7118         layer->texture = texture;
7119         layer->texmatrix = *matrix;
7120         layer->color[0] = r;
7121         layer->color[1] = g;
7122         layer->color[2] = b;
7123         layer->color[3] = a;
7124 }
7125
7126 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7127 {
7128         if(parms[0] == 0 && parms[1] == 0)
7129                 return false;
7130         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7131                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7132                         return false;
7133         return true;
7134 }
7135
7136 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7137 {
7138         double index, f;
7139         index = parms[2] + r_refdef.scene.time * parms[3];
7140         index -= floor(index);
7141         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7142         {
7143         default:
7144         case Q3WAVEFUNC_NONE:
7145         case Q3WAVEFUNC_NOISE:
7146         case Q3WAVEFUNC_COUNT:
7147                 f = 0;
7148                 break;
7149         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7150         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7151         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7152         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7153         case Q3WAVEFUNC_TRIANGLE:
7154                 index *= 4;
7155                 f = index - floor(index);
7156                 if (index < 1)
7157                         f = f;
7158                 else if (index < 2)
7159                         f = 1 - f;
7160                 else if (index < 3)
7161                         f = -f;
7162                 else
7163                         f = -(1 - f);
7164                 break;
7165         }
7166         f = parms[0] + parms[1] * f;
7167         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7168                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7169         return (float) f;
7170 }
7171
7172 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7173 {
7174         int w, h, idx;
7175         float f;
7176         float tcmat[12];
7177         matrix4x4_t matrix, temp;
7178         switch(tcmod->tcmod)
7179         {
7180                 case Q3TCMOD_COUNT:
7181                 case Q3TCMOD_NONE:
7182                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7183                                 matrix = r_waterscrollmatrix;
7184                         else
7185                                 matrix = identitymatrix;
7186                         break;
7187                 case Q3TCMOD_ENTITYTRANSLATE:
7188                         // this is used in Q3 to allow the gamecode to control texcoord
7189                         // scrolling on the entity, which is not supported in darkplaces yet.
7190                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7191                         break;
7192                 case Q3TCMOD_ROTATE:
7193                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7194                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7195                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7196                         break;
7197                 case Q3TCMOD_SCALE:
7198                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7199                         break;
7200                 case Q3TCMOD_SCROLL:
7201                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7202                         break;
7203                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7204                         w = (int) tcmod->parms[0];
7205                         h = (int) tcmod->parms[1];
7206                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7207                         f = f - floor(f);
7208                         idx = (int) floor(f * w * h);
7209                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7210                         break;
7211                 case Q3TCMOD_STRETCH:
7212                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7213                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7214                         break;
7215                 case Q3TCMOD_TRANSFORM:
7216                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7217                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7218                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7219                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7220                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7221                         break;
7222                 case Q3TCMOD_TURBULENT:
7223                         // this is handled in the RSurf_PrepareVertices function
7224                         matrix = identitymatrix;
7225                         break;
7226         }
7227         temp = *texmatrix;
7228         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7229 }
7230
7231 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7232 {
7233         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7234         char name[MAX_QPATH];
7235         skinframe_t *skinframe;
7236         unsigned char pixels[296*194];
7237         strlcpy(cache->name, skinname, sizeof(cache->name));
7238         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7239         if (developer_loading.integer)
7240                 Con_Printf("loading %s\n", name);
7241         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7242         if (!skinframe || !skinframe->base)
7243         {
7244                 unsigned char *f;
7245                 fs_offset_t filesize;
7246                 skinframe = NULL;
7247                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7248                 if (f)
7249                 {
7250                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7251                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7252                         Mem_Free(f);
7253                 }
7254         }
7255         cache->skinframe = skinframe;
7256 }
7257
7258 texture_t *R_GetCurrentTexture(texture_t *t)
7259 {
7260         int i;
7261         const entity_render_t *ent = rsurface.entity;
7262         dp_model_t *model = ent->model;
7263         q3shaderinfo_layer_tcmod_t *tcmod;
7264
7265         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7266                 return t->currentframe;
7267         t->update_lastrenderframe = r_textureframe;
7268         t->update_lastrenderentity = (void *)ent;
7269
7270         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7271                 t->camera_entity = ent->entitynumber;
7272         else
7273                 t->camera_entity = 0;
7274
7275         // switch to an alternate material if this is a q1bsp animated material
7276         {
7277                 texture_t *texture = t;
7278                 int s = rsurface.ent_skinnum;
7279                 if ((unsigned int)s >= (unsigned int)model->numskins)
7280                         s = 0;
7281                 if (model->skinscenes)
7282                 {
7283                         if (model->skinscenes[s].framecount > 1)
7284                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7285                         else
7286                                 s = model->skinscenes[s].firstframe;
7287                 }
7288                 if (s > 0)
7289                         t = t + s * model->num_surfaces;
7290                 if (t->animated)
7291                 {
7292                         // use an alternate animation if the entity's frame is not 0,
7293                         // and only if the texture has an alternate animation
7294                         if (rsurface.ent_alttextures && t->anim_total[1])
7295                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7296                         else
7297                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7298                 }
7299                 texture->currentframe = t;
7300         }
7301
7302         // update currentskinframe to be a qw skin or animation frame
7303         if (rsurface.ent_qwskin >= 0)
7304         {
7305                 i = rsurface.ent_qwskin;
7306                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7307                 {
7308                         r_qwskincache_size = cl.maxclients;
7309                         if (r_qwskincache)
7310                                 Mem_Free(r_qwskincache);
7311                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7312                 }
7313                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7314                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7315                 t->currentskinframe = r_qwskincache[i].skinframe;
7316                 if (t->currentskinframe == NULL)
7317                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7318         }
7319         else if (t->numskinframes >= 2)
7320                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7321         if (t->backgroundnumskinframes >= 2)
7322                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7323
7324         t->currentmaterialflags = t->basematerialflags;
7325         t->currentalpha = rsurface.colormod[3];
7326         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7327                 t->currentalpha *= r_wateralpha.value;
7328         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7329                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7330         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7331                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7332         if (!(rsurface.ent_flags & RENDER_LIGHT))
7333                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7334         else if (FAKELIGHT_ENABLED)
7335         {
7336                         // no modellight if using fakelight for the map
7337         }
7338         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7339         {
7340                 // pick a model lighting mode
7341                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7342                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7343                 else
7344                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7345         }
7346         if (rsurface.ent_flags & RENDER_ADDITIVE)
7347                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7348         else if (t->currentalpha < 1)
7349                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7350         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7351                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7352         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7353                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7354         if (t->backgroundnumskinframes)
7355                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7356         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7357         {
7358                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7359                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7360         }
7361         else
7362                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7363         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7364                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7365
7366         // there is no tcmod
7367         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7368         {
7369                 t->currenttexmatrix = r_waterscrollmatrix;
7370                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7371         }
7372         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7373         {
7374                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7375                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7376         }
7377
7378         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7379                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7380         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7381                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7382
7383         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7384         if (t->currentskinframe->qpixels)
7385                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7386         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7387         if (!t->basetexture)
7388                 t->basetexture = r_texture_notexture;
7389         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7390         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7391         t->nmaptexture = t->currentskinframe->nmap;
7392         if (!t->nmaptexture)
7393                 t->nmaptexture = r_texture_blanknormalmap;
7394         t->glosstexture = r_texture_black;
7395         t->glowtexture = t->currentskinframe->glow;
7396         t->fogtexture = t->currentskinframe->fog;
7397         t->reflectmasktexture = t->currentskinframe->reflect;
7398         if (t->backgroundnumskinframes)
7399         {
7400                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7401                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7402                 t->backgroundglosstexture = r_texture_black;
7403                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7404                 if (!t->backgroundnmaptexture)
7405                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7406         }
7407         else
7408         {
7409                 t->backgroundbasetexture = r_texture_white;
7410                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7411                 t->backgroundglosstexture = r_texture_black;
7412                 t->backgroundglowtexture = NULL;
7413         }
7414         t->specularpower = r_shadow_glossexponent.value;
7415         // TODO: store reference values for these in the texture?
7416         t->specularscale = 0;
7417         if (r_shadow_gloss.integer > 0)
7418         {
7419                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7420                 {
7421                         if (r_shadow_glossintensity.value > 0)
7422                         {
7423                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7424                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7425                                 t->specularscale = r_shadow_glossintensity.value;
7426                         }
7427                 }
7428                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7429                 {
7430                         t->glosstexture = r_texture_white;
7431                         t->backgroundglosstexture = r_texture_white;
7432                         t->specularscale = r_shadow_gloss2intensity.value;
7433                         t->specularpower = r_shadow_gloss2exponent.value;
7434                 }
7435         }
7436         t->specularscale *= t->specularscalemod;
7437         t->specularpower *= t->specularpowermod;
7438
7439         // lightmaps mode looks bad with dlights using actual texturing, so turn
7440         // off the colormap and glossmap, but leave the normalmap on as it still
7441         // accurately represents the shading involved
7442         if (gl_lightmaps.integer)
7443         {
7444                 t->basetexture = r_texture_grey128;
7445                 t->pantstexture = r_texture_black;
7446                 t->shirttexture = r_texture_black;
7447                 t->nmaptexture = r_texture_blanknormalmap;
7448                 t->glosstexture = r_texture_black;
7449                 t->glowtexture = NULL;
7450                 t->fogtexture = NULL;
7451                 t->reflectmasktexture = NULL;
7452                 t->backgroundbasetexture = NULL;
7453                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7454                 t->backgroundglosstexture = r_texture_black;
7455                 t->backgroundglowtexture = NULL;
7456                 t->specularscale = 0;
7457                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7458         }
7459
7460         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7461         VectorClear(t->dlightcolor);
7462         t->currentnumlayers = 0;
7463         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7464         {
7465                 int blendfunc1, blendfunc2;
7466                 qboolean depthmask;
7467                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7468                 {
7469                         blendfunc1 = GL_SRC_ALPHA;
7470                         blendfunc2 = GL_ONE;
7471                 }
7472                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7473                 {
7474                         blendfunc1 = GL_SRC_ALPHA;
7475                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7476                 }
7477                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7478                 {
7479                         blendfunc1 = t->customblendfunc[0];
7480                         blendfunc2 = t->customblendfunc[1];
7481                 }
7482                 else
7483                 {
7484                         blendfunc1 = GL_ONE;
7485                         blendfunc2 = GL_ZERO;
7486                 }
7487                 // don't colormod evilblend textures
7488                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7489                         VectorSet(t->lightmapcolor, 1, 1, 1);
7490                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7491                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7492                 {
7493                         // fullbright is not affected by r_refdef.lightmapintensity
7494                         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]);
7495                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7496                                 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]);
7497                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7498                                 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]);
7499                 }
7500                 else
7501                 {
7502                         vec3_t ambientcolor;
7503                         float colorscale;
7504                         // set the color tint used for lights affecting this surface
7505                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7506                         colorscale = 2;
7507                         // q3bsp has no lightmap updates, so the lightstylevalue that
7508                         // would normally be baked into the lightmap must be
7509                         // applied to the color
7510                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7511                         if (model->type == mod_brushq3)
7512                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7513                         colorscale *= r_refdef.lightmapintensity;
7514                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7515                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7516                         // basic lit geometry
7517                         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]);
7518                         // add pants/shirt if needed
7519                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7520                                 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]);
7521                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7522                                 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]);
7523                         // now add ambient passes if needed
7524                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7525                         {
7526                                 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]);
7527                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7528                                         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]);
7529                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7530                                         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]);
7531                         }
7532                 }
7533                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7534                         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]);
7535                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7536                 {
7537                         // if this is opaque use alpha blend which will darken the earlier
7538                         // passes cheaply.
7539                         //
7540                         // if this is an alpha blended material, all the earlier passes
7541                         // were darkened by fog already, so we only need to add the fog
7542                         // color ontop through the fog mask texture
7543                         //
7544                         // if this is an additive blended material, all the earlier passes
7545                         // were darkened by fog already, and we should not add fog color
7546                         // (because the background was not darkened, there is no fog color
7547                         // that was lost behind it).
7548                         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]);
7549                 }
7550         }
7551
7552         return t->currentframe;
7553 }
7554
7555 rsurfacestate_t rsurface;
7556
7557 void RSurf_ActiveWorldEntity(void)
7558 {
7559         dp_model_t *model = r_refdef.scene.worldmodel;
7560         //if (rsurface.entity == r_refdef.scene.worldentity)
7561         //      return;
7562         rsurface.entity = r_refdef.scene.worldentity;
7563         rsurface.skeleton = NULL;
7564         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7565         rsurface.ent_skinnum = 0;
7566         rsurface.ent_qwskin = -1;
7567         rsurface.ent_shadertime = 0;
7568         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7569         rsurface.matrix = identitymatrix;
7570         rsurface.inversematrix = identitymatrix;
7571         rsurface.matrixscale = 1;
7572         rsurface.inversematrixscale = 1;
7573         R_EntityMatrix(&identitymatrix);
7574         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7575         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7576         rsurface.fograngerecip = r_refdef.fograngerecip;
7577         rsurface.fogheightfade = r_refdef.fogheightfade;
7578         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7579         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7580         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7581         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7582         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7583         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7584         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7585         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7586         rsurface.colormod[3] = 1;
7587         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);
7588         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7589         rsurface.frameblend[0].lerp = 1;
7590         rsurface.ent_alttextures = false;
7591         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7592         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7593         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7594         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7595         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7596         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7597         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7598         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7599         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7600         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7601         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7602         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7603         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7604         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7605         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7606         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7607         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7608         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7609         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7610         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7611         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7612         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7613         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7614         rsurface.modelelement3i = model->surfmesh.data_element3i;
7615         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7616         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7617         rsurface.modelelement3s = model->surfmesh.data_element3s;
7618         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7619         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7620         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7621         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7622         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7623         rsurface.modelsurfaces = model->data_surfaces;
7624         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7625         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7626         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7627         rsurface.modelgeneratedvertex = false;
7628         rsurface.batchgeneratedvertex = false;
7629         rsurface.batchfirstvertex = 0;
7630         rsurface.batchnumvertices = 0;
7631         rsurface.batchfirsttriangle = 0;
7632         rsurface.batchnumtriangles = 0;
7633         rsurface.batchvertex3f  = NULL;
7634         rsurface.batchvertex3f_vertexbuffer = NULL;
7635         rsurface.batchvertex3f_bufferoffset = 0;
7636         rsurface.batchsvector3f = NULL;
7637         rsurface.batchsvector3f_vertexbuffer = NULL;
7638         rsurface.batchsvector3f_bufferoffset = 0;
7639         rsurface.batchtvector3f = NULL;
7640         rsurface.batchtvector3f_vertexbuffer = NULL;
7641         rsurface.batchtvector3f_bufferoffset = 0;
7642         rsurface.batchnormal3f  = NULL;
7643         rsurface.batchnormal3f_vertexbuffer = NULL;
7644         rsurface.batchnormal3f_bufferoffset = 0;
7645         rsurface.batchlightmapcolor4f = NULL;
7646         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7647         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7648         rsurface.batchtexcoordtexture2f = NULL;
7649         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7650         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7651         rsurface.batchtexcoordlightmap2f = NULL;
7652         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7653         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7654         rsurface.batchvertexmesh = NULL;
7655         rsurface.batchvertexmeshbuffer = NULL;
7656         rsurface.batchvertex3fbuffer = NULL;
7657         rsurface.batchelement3i = NULL;
7658         rsurface.batchelement3i_indexbuffer = NULL;
7659         rsurface.batchelement3i_bufferoffset = 0;
7660         rsurface.batchelement3s = NULL;
7661         rsurface.batchelement3s_indexbuffer = NULL;
7662         rsurface.batchelement3s_bufferoffset = 0;
7663         rsurface.passcolor4f = NULL;
7664         rsurface.passcolor4f_vertexbuffer = NULL;
7665         rsurface.passcolor4f_bufferoffset = 0;
7666 }
7667
7668 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7669 {
7670         dp_model_t *model = ent->model;
7671         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7672         //      return;
7673         rsurface.entity = (entity_render_t *)ent;
7674         rsurface.skeleton = ent->skeleton;
7675         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7676         rsurface.ent_skinnum = ent->skinnum;
7677         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;
7678         rsurface.ent_shadertime = ent->shadertime;
7679         rsurface.ent_flags = ent->flags;
7680         rsurface.matrix = ent->matrix;
7681         rsurface.inversematrix = ent->inversematrix;
7682         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7683         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7684         R_EntityMatrix(&rsurface.matrix);
7685         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7686         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7687         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7688         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7689         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7690         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7691         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7692         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7693         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7694         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7695         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7696         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7697         rsurface.colormod[3] = ent->alpha;
7698         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7699         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7700         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7701         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7702         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7703         if (ent->model->brush.submodel && !prepass)
7704         {
7705                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7706                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7707         }
7708         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7709         {
7710                 if (ent->animcache_vertex3f)
7711                 {
7712                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7713                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7714                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7715                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7716                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7717                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7718                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7719                 }
7720                 else if (wanttangents)
7721                 {
7722                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7723                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7724                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7725                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7726                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7727                         rsurface.modelvertexmesh = NULL;
7728                         rsurface.modelvertexmeshbuffer = NULL;
7729                         rsurface.modelvertex3fbuffer = NULL;
7730                 }
7731                 else if (wantnormals)
7732                 {
7733                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7734                         rsurface.modelsvector3f = NULL;
7735                         rsurface.modeltvector3f = NULL;
7736                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7737                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7738                         rsurface.modelvertexmesh = NULL;
7739                         rsurface.modelvertexmeshbuffer = NULL;
7740                         rsurface.modelvertex3fbuffer = NULL;
7741                 }
7742                 else
7743                 {
7744                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7745                         rsurface.modelsvector3f = NULL;
7746                         rsurface.modeltvector3f = NULL;
7747                         rsurface.modelnormal3f = NULL;
7748                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7749                         rsurface.modelvertexmesh = NULL;
7750                         rsurface.modelvertexmeshbuffer = NULL;
7751                         rsurface.modelvertex3fbuffer = NULL;
7752                 }
7753                 rsurface.modelvertex3f_vertexbuffer = 0;
7754                 rsurface.modelvertex3f_bufferoffset = 0;
7755                 rsurface.modelsvector3f_vertexbuffer = 0;
7756                 rsurface.modelsvector3f_bufferoffset = 0;
7757                 rsurface.modeltvector3f_vertexbuffer = 0;
7758                 rsurface.modeltvector3f_bufferoffset = 0;
7759                 rsurface.modelnormal3f_vertexbuffer = 0;
7760                 rsurface.modelnormal3f_bufferoffset = 0;
7761                 rsurface.modelgeneratedvertex = true;
7762         }
7763         else
7764         {
7765                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7766                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7767                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7768                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7769                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7770                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7771                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7772                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7773                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7774                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7775                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7776                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7777                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7778                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7779                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7780                 rsurface.modelgeneratedvertex = false;
7781         }
7782         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7783         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7784         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7785         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7786         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7787         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7788         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7789         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7790         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7791         rsurface.modelelement3i = model->surfmesh.data_element3i;
7792         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7793         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7794         rsurface.modelelement3s = model->surfmesh.data_element3s;
7795         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7796         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7797         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7798         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7799         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7800         rsurface.modelsurfaces = model->data_surfaces;
7801         rsurface.batchgeneratedvertex = false;
7802         rsurface.batchfirstvertex = 0;
7803         rsurface.batchnumvertices = 0;
7804         rsurface.batchfirsttriangle = 0;
7805         rsurface.batchnumtriangles = 0;
7806         rsurface.batchvertex3f  = NULL;
7807         rsurface.batchvertex3f_vertexbuffer = NULL;
7808         rsurface.batchvertex3f_bufferoffset = 0;
7809         rsurface.batchsvector3f = NULL;
7810         rsurface.batchsvector3f_vertexbuffer = NULL;
7811         rsurface.batchsvector3f_bufferoffset = 0;
7812         rsurface.batchtvector3f = NULL;
7813         rsurface.batchtvector3f_vertexbuffer = NULL;
7814         rsurface.batchtvector3f_bufferoffset = 0;
7815         rsurface.batchnormal3f  = NULL;
7816         rsurface.batchnormal3f_vertexbuffer = NULL;
7817         rsurface.batchnormal3f_bufferoffset = 0;
7818         rsurface.batchlightmapcolor4f = NULL;
7819         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7820         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7821         rsurface.batchtexcoordtexture2f = NULL;
7822         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7823         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7824         rsurface.batchtexcoordlightmap2f = NULL;
7825         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7826         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7827         rsurface.batchvertexmesh = NULL;
7828         rsurface.batchvertexmeshbuffer = NULL;
7829         rsurface.batchvertex3fbuffer = NULL;
7830         rsurface.batchelement3i = NULL;
7831         rsurface.batchelement3i_indexbuffer = NULL;
7832         rsurface.batchelement3i_bufferoffset = 0;
7833         rsurface.batchelement3s = NULL;
7834         rsurface.batchelement3s_indexbuffer = NULL;
7835         rsurface.batchelement3s_bufferoffset = 0;
7836         rsurface.passcolor4f = NULL;
7837         rsurface.passcolor4f_vertexbuffer = NULL;
7838         rsurface.passcolor4f_bufferoffset = 0;
7839 }
7840
7841 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)
7842 {
7843         rsurface.entity = r_refdef.scene.worldentity;
7844         rsurface.skeleton = NULL;
7845         rsurface.ent_skinnum = 0;
7846         rsurface.ent_qwskin = -1;
7847         rsurface.ent_shadertime = shadertime;
7848         rsurface.ent_flags = entflags;
7849         rsurface.modelnumvertices = numvertices;
7850         rsurface.modelnumtriangles = numtriangles;
7851         rsurface.matrix = *matrix;
7852         rsurface.inversematrix = *inversematrix;
7853         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7854         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7855         R_EntityMatrix(&rsurface.matrix);
7856         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7857         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7858         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7859         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7860         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7861         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7862         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7863         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7864         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7865         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7866         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7867         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7868         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);
7869         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7870         rsurface.frameblend[0].lerp = 1;
7871         rsurface.ent_alttextures = false;
7872         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7873         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7874         if (wanttangents)
7875         {
7876                 rsurface.modelvertex3f = (float *)vertex3f;
7877                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7878                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7879                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7880         }
7881         else if (wantnormals)
7882         {
7883                 rsurface.modelvertex3f = (float *)vertex3f;
7884                 rsurface.modelsvector3f = NULL;
7885                 rsurface.modeltvector3f = NULL;
7886                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7887         }
7888         else
7889         {
7890                 rsurface.modelvertex3f = (float *)vertex3f;
7891                 rsurface.modelsvector3f = NULL;
7892                 rsurface.modeltvector3f = NULL;
7893                 rsurface.modelnormal3f = NULL;
7894         }
7895         rsurface.modelvertexmesh = NULL;
7896         rsurface.modelvertexmeshbuffer = NULL;
7897         rsurface.modelvertex3fbuffer = NULL;
7898         rsurface.modelvertex3f_vertexbuffer = 0;
7899         rsurface.modelvertex3f_bufferoffset = 0;
7900         rsurface.modelsvector3f_vertexbuffer = 0;
7901         rsurface.modelsvector3f_bufferoffset = 0;
7902         rsurface.modeltvector3f_vertexbuffer = 0;
7903         rsurface.modeltvector3f_bufferoffset = 0;
7904         rsurface.modelnormal3f_vertexbuffer = 0;
7905         rsurface.modelnormal3f_bufferoffset = 0;
7906         rsurface.modelgeneratedvertex = true;
7907         rsurface.modellightmapcolor4f  = (float *)color4f;
7908         rsurface.modellightmapcolor4f_vertexbuffer = 0;
7909         rsurface.modellightmapcolor4f_bufferoffset = 0;
7910         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
7911         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7912         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7913         rsurface.modeltexcoordlightmap2f  = NULL;
7914         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7915         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7916         rsurface.modelelement3i = (int *)element3i;
7917         rsurface.modelelement3i_indexbuffer = NULL;
7918         rsurface.modelelement3i_bufferoffset = 0;
7919         rsurface.modelelement3s = (unsigned short *)element3s;
7920         rsurface.modelelement3s_indexbuffer = NULL;
7921         rsurface.modelelement3s_bufferoffset = 0;
7922         rsurface.modellightmapoffsets = NULL;
7923         rsurface.modelsurfaces = NULL;
7924         rsurface.batchgeneratedvertex = false;
7925         rsurface.batchfirstvertex = 0;
7926         rsurface.batchnumvertices = 0;
7927         rsurface.batchfirsttriangle = 0;
7928         rsurface.batchnumtriangles = 0;
7929         rsurface.batchvertex3f  = NULL;
7930         rsurface.batchvertex3f_vertexbuffer = NULL;
7931         rsurface.batchvertex3f_bufferoffset = 0;
7932         rsurface.batchsvector3f = NULL;
7933         rsurface.batchsvector3f_vertexbuffer = NULL;
7934         rsurface.batchsvector3f_bufferoffset = 0;
7935         rsurface.batchtvector3f = NULL;
7936         rsurface.batchtvector3f_vertexbuffer = NULL;
7937         rsurface.batchtvector3f_bufferoffset = 0;
7938         rsurface.batchnormal3f  = NULL;
7939         rsurface.batchnormal3f_vertexbuffer = NULL;
7940         rsurface.batchnormal3f_bufferoffset = 0;
7941         rsurface.batchlightmapcolor4f = NULL;
7942         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7943         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7944         rsurface.batchtexcoordtexture2f = NULL;
7945         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7946         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7947         rsurface.batchtexcoordlightmap2f = NULL;
7948         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7949         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7950         rsurface.batchvertexmesh = NULL;
7951         rsurface.batchvertexmeshbuffer = NULL;
7952         rsurface.batchvertex3fbuffer = NULL;
7953         rsurface.batchelement3i = NULL;
7954         rsurface.batchelement3i_indexbuffer = NULL;
7955         rsurface.batchelement3i_bufferoffset = 0;
7956         rsurface.batchelement3s = NULL;
7957         rsurface.batchelement3s_indexbuffer = NULL;
7958         rsurface.batchelement3s_bufferoffset = 0;
7959         rsurface.passcolor4f = NULL;
7960         rsurface.passcolor4f_vertexbuffer = NULL;
7961         rsurface.passcolor4f_bufferoffset = 0;
7962
7963         if (rsurface.modelnumvertices && rsurface.modelelement3i)
7964         {
7965                 if ((wantnormals || wanttangents) && !normal3f)
7966                 {
7967                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7968                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7969                 }
7970                 if (wanttangents && !svector3f)
7971                 {
7972                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7973                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7974                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7975                 }
7976         }
7977 }
7978
7979 float RSurf_FogPoint(const float *v)
7980 {
7981         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7982         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7983         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7984         float FogHeightFade = r_refdef.fogheightfade;
7985         float fogfrac;
7986         unsigned int fogmasktableindex;
7987         if (r_refdef.fogplaneviewabove)
7988                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7989         else
7990                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7991         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7992         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7993 }
7994
7995 float RSurf_FogVertex(const float *v)
7996 {
7997         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7998         float FogPlaneViewDist = rsurface.fogplaneviewdist;
7999         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8000         float FogHeightFade = rsurface.fogheightfade;
8001         float fogfrac;
8002         unsigned int fogmasktableindex;
8003         if (r_refdef.fogplaneviewabove)
8004                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8005         else
8006                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8007         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8008         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8009 }
8010
8011 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8012 {
8013         int i;
8014         for (i = 0;i < numelements;i++)
8015                 outelement3i[i] = inelement3i[i] + adjust;
8016 }
8017
8018 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8019 extern cvar_t gl_vbo;
8020 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8021 {
8022         int deformindex;
8023         int firsttriangle;
8024         int numtriangles;
8025         int firstvertex;
8026         int endvertex;
8027         int numvertices;
8028         int surfacefirsttriangle;
8029         int surfacenumtriangles;
8030         int surfacefirstvertex;
8031         int surfaceendvertex;
8032         int surfacenumvertices;
8033         int batchnumvertices;
8034         int batchnumtriangles;
8035         int needsupdate;
8036         int i, j;
8037         qboolean gaps;
8038         qboolean dynamicvertex;
8039         float amplitude;
8040         float animpos;
8041         float scale;
8042         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8043         float waveparms[4];
8044         q3shaderinfo_deform_t *deform;
8045         const msurface_t *surface, *firstsurface;
8046         r_vertexmesh_t *vertexmesh;
8047         if (!texturenumsurfaces)
8048                 return;
8049         // find vertex range of this surface batch
8050         gaps = false;
8051         firstsurface = texturesurfacelist[0];
8052         firsttriangle = firstsurface->num_firsttriangle;
8053         batchnumvertices = 0;
8054         batchnumtriangles = 0;
8055         firstvertex = endvertex = firstsurface->num_firstvertex;
8056         for (i = 0;i < texturenumsurfaces;i++)
8057         {
8058                 surface = texturesurfacelist[i];
8059                 if (surface != firstsurface + i)
8060                         gaps = true;
8061                 surfacefirstvertex = surface->num_firstvertex;
8062                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8063                 surfacenumvertices = surface->num_vertices;
8064                 surfacenumtriangles = surface->num_triangles;
8065                 if (firstvertex > surfacefirstvertex)
8066                         firstvertex = surfacefirstvertex;
8067                 if (endvertex < surfaceendvertex)
8068                         endvertex = surfaceendvertex;
8069                 batchnumvertices += surfacenumvertices;
8070                 batchnumtriangles += surfacenumtriangles;
8071         }
8072
8073         // we now know the vertex range used, and if there are any gaps in it
8074         rsurface.batchfirstvertex = firstvertex;
8075         rsurface.batchnumvertices = endvertex - firstvertex;
8076         rsurface.batchfirsttriangle = firsttriangle;
8077         rsurface.batchnumtriangles = batchnumtriangles;
8078
8079         // this variable holds flags for which properties have been updated that
8080         // may require regenerating vertexmesh array...
8081         needsupdate = 0;
8082
8083         // check if any dynamic vertex processing must occur
8084         dynamicvertex = false;
8085
8086         // if there is a chance of animated vertex colors, it's a dynamic batch
8087         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8088         {
8089                 dynamicvertex = true;
8090                 batchneed |= BATCHNEED_NOGAPS;
8091                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8092         }
8093
8094         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8095         {
8096                 switch (deform->deform)
8097                 {
8098                 default:
8099                 case Q3DEFORM_PROJECTIONSHADOW:
8100                 case Q3DEFORM_TEXT0:
8101                 case Q3DEFORM_TEXT1:
8102                 case Q3DEFORM_TEXT2:
8103                 case Q3DEFORM_TEXT3:
8104                 case Q3DEFORM_TEXT4:
8105                 case Q3DEFORM_TEXT5:
8106                 case Q3DEFORM_TEXT6:
8107                 case Q3DEFORM_TEXT7:
8108                 case Q3DEFORM_NONE:
8109                         break;
8110                 case Q3DEFORM_AUTOSPRITE:
8111                         dynamicvertex = true;
8112                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8113                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8114                         break;
8115                 case Q3DEFORM_AUTOSPRITE2:
8116                         dynamicvertex = true;
8117                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8118                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8119                         break;
8120                 case Q3DEFORM_NORMAL:
8121                         dynamicvertex = true;
8122                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8123                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8124                         break;
8125                 case Q3DEFORM_WAVE:
8126                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8127                                 break; // if wavefunc is a nop, ignore this transform
8128                         dynamicvertex = true;
8129                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8130                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8131                         break;
8132                 case Q3DEFORM_BULGE:
8133                         dynamicvertex = true;
8134                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8135                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8136                         break;
8137                 case Q3DEFORM_MOVE:
8138                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8139                                 break; // if wavefunc is a nop, ignore this transform
8140                         dynamicvertex = true;
8141                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8142                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8143                         break;
8144                 }
8145         }
8146         switch(rsurface.texture->tcgen.tcgen)
8147         {
8148         default:
8149         case Q3TCGEN_TEXTURE:
8150                 break;
8151         case Q3TCGEN_LIGHTMAP:
8152                 dynamicvertex = true;
8153                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8154                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8155                 break;
8156         case Q3TCGEN_VECTOR:
8157                 dynamicvertex = true;
8158                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8159                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8160                 break;
8161         case Q3TCGEN_ENVIRONMENT:
8162                 dynamicvertex = true;
8163                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8164                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8165                 break;
8166         }
8167         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8168         {
8169                 dynamicvertex = true;
8170                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8171                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8172         }
8173
8174         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8175         {
8176                 dynamicvertex = true;
8177                 batchneed |= BATCHNEED_NOGAPS;
8178                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8179         }
8180
8181         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8182         {
8183                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8184                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8185                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8186                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8187                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8188                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8189                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8190         }
8191
8192         // when the model data has no vertex buffer (dynamic mesh), we need to
8193         // eliminate gaps
8194         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8195                 batchneed |= BATCHNEED_NOGAPS;
8196
8197         // if needsupdate, we have to do a dynamic vertex batch for sure
8198         if (needsupdate & batchneed)
8199                 dynamicvertex = true;
8200
8201         // see if we need to build vertexmesh from arrays
8202         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8203                 dynamicvertex = true;
8204
8205         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8206         // also some drivers strongly dislike firstvertex
8207         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8208                 dynamicvertex = true;
8209
8210         rsurface.batchvertex3f = rsurface.modelvertex3f;
8211         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8212         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8213         rsurface.batchsvector3f = rsurface.modelsvector3f;
8214         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8215         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8216         rsurface.batchtvector3f = rsurface.modeltvector3f;
8217         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8218         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8219         rsurface.batchnormal3f = rsurface.modelnormal3f;
8220         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8221         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8222         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8223         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8224         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8225         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8226         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8227         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8228         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8229         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8230         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8231         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8232         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8233         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8234         rsurface.batchelement3i = rsurface.modelelement3i;
8235         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8236         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8237         rsurface.batchelement3s = rsurface.modelelement3s;
8238         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8239         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8240
8241         // if any dynamic vertex processing has to occur in software, we copy the
8242         // entire surface list together before processing to rebase the vertices
8243         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8244         //
8245         // if any gaps exist and we do not have a static vertex buffer, we have to
8246         // copy the surface list together to avoid wasting upload bandwidth on the
8247         // vertices in the gaps.
8248         //
8249         // if gaps exist and we have a static vertex buffer, we still have to
8250         // combine the index buffer ranges into one dynamic index buffer.
8251         //
8252         // in all cases we end up with data that can be drawn in one call.
8253
8254         if (!dynamicvertex)
8255         {
8256                 // static vertex data, just set pointers...
8257                 rsurface.batchgeneratedvertex = false;
8258                 // if there are gaps, we want to build a combined index buffer,
8259                 // otherwise use the original static buffer with an appropriate offset
8260                 if (gaps)
8261                 {
8262                         // build a new triangle elements array for this batch
8263                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8264                         rsurface.batchfirsttriangle = 0;
8265                         numtriangles = 0;
8266                         for (i = 0;i < texturenumsurfaces;i++)
8267                         {
8268                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8269                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8270                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8271                                 numtriangles += surfacenumtriangles;
8272                         }
8273                         rsurface.batchelement3i_indexbuffer = NULL;
8274                         rsurface.batchelement3i_bufferoffset = 0;
8275                         rsurface.batchelement3s = NULL;
8276                         rsurface.batchelement3s_indexbuffer = NULL;
8277                         rsurface.batchelement3s_bufferoffset = 0;
8278                         if (endvertex <= 65536)
8279                         {
8280                                 // make a 16bit (unsigned short) index array if possible
8281                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8282                                 for (i = 0;i < numtriangles*3;i++)
8283                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8284                         }
8285                 }
8286                 return;
8287         }
8288
8289         // something needs software processing, do it for real...
8290         // we only directly handle separate array data in this case and then
8291         // generate interleaved data if needed...
8292         rsurface.batchgeneratedvertex = true;
8293
8294         // now copy the vertex data into a combined array and make an index array
8295         // (this is what Quake3 does all the time)
8296         //if (gaps || rsurface.batchfirstvertex)
8297         {
8298                 rsurface.batchvertex3fbuffer = NULL;
8299                 rsurface.batchvertexmesh = NULL;
8300                 rsurface.batchvertexmeshbuffer = NULL;
8301                 rsurface.batchvertex3f = NULL;
8302                 rsurface.batchvertex3f_vertexbuffer = NULL;
8303                 rsurface.batchvertex3f_bufferoffset = 0;
8304                 rsurface.batchsvector3f = NULL;
8305                 rsurface.batchsvector3f_vertexbuffer = NULL;
8306                 rsurface.batchsvector3f_bufferoffset = 0;
8307                 rsurface.batchtvector3f = NULL;
8308                 rsurface.batchtvector3f_vertexbuffer = NULL;
8309                 rsurface.batchtvector3f_bufferoffset = 0;
8310                 rsurface.batchnormal3f = NULL;
8311                 rsurface.batchnormal3f_vertexbuffer = NULL;
8312                 rsurface.batchnormal3f_bufferoffset = 0;
8313                 rsurface.batchlightmapcolor4f = NULL;
8314                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8315                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8316                 rsurface.batchtexcoordtexture2f = NULL;
8317                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8318                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8319                 rsurface.batchtexcoordlightmap2f = NULL;
8320                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8321                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8322                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8323                 rsurface.batchelement3i_indexbuffer = NULL;
8324                 rsurface.batchelement3i_bufferoffset = 0;
8325                 rsurface.batchelement3s = NULL;
8326                 rsurface.batchelement3s_indexbuffer = NULL;
8327                 rsurface.batchelement3s_bufferoffset = 0;
8328                 // we'll only be setting up certain arrays as needed
8329                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8330                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8331                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8332                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8333                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8334                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8335                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8336                 {
8337                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8338                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8339                 }
8340                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8341                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8342                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8343                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8344                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8345                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8346                 numvertices = 0;
8347                 numtriangles = 0;
8348                 for (i = 0;i < texturenumsurfaces;i++)
8349                 {
8350                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8351                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8352                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8353                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8354                         // copy only the data requested
8355                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8356                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8357                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8358                         {
8359                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8360                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8361                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8362                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8363                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8364                                 {
8365                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8366                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8367                                 }
8368                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8369                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8370                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8371                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8372                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8373                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8374                         }
8375                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8376                         numvertices += surfacenumvertices;
8377                         numtriangles += surfacenumtriangles;
8378                 }
8379
8380                 // generate a 16bit index array as well if possible
8381                 // (in general, dynamic batches fit)
8382                 if (numvertices <= 65536)
8383                 {
8384                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8385                         for (i = 0;i < numtriangles*3;i++)
8386                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8387                 }
8388
8389                 // since we've copied everything, the batch now starts at 0
8390                 rsurface.batchfirstvertex = 0;
8391                 rsurface.batchnumvertices = batchnumvertices;
8392                 rsurface.batchfirsttriangle = 0;
8393                 rsurface.batchnumtriangles = batchnumtriangles;
8394         }
8395
8396         // q1bsp surfaces rendered in vertex color mode have to have colors
8397         // calculated based on lightstyles
8398         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8399         {
8400                 // generate color arrays for the surfaces in this list
8401                 int c[4];
8402                 int scale;
8403                 int size3;
8404                 const int *offsets;
8405                 const unsigned char *lm;
8406                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8407                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8408                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8409                 numvertices = 0;
8410                 for (i = 0;i < texturenumsurfaces;i++)
8411                 {
8412                         surface = texturesurfacelist[i];
8413                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8414                         surfacenumvertices = surface->num_vertices;
8415                         if (surface->lightmapinfo->samples)
8416                         {
8417                                 for (j = 0;j < surfacenumvertices;j++)
8418                                 {
8419                                         lm = surface->lightmapinfo->samples + offsets[j];
8420                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8421                                         VectorScale(lm, scale, c);
8422                                         if (surface->lightmapinfo->styles[1] != 255)
8423                                         {
8424                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8425                                                 lm += size3;
8426                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8427                                                 VectorMA(c, scale, lm, c);
8428                                                 if (surface->lightmapinfo->styles[2] != 255)
8429                                                 {
8430                                                         lm += size3;
8431                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8432                                                         VectorMA(c, scale, lm, c);
8433                                                         if (surface->lightmapinfo->styles[3] != 255)
8434                                                         {
8435                                                                 lm += size3;
8436                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8437                                                                 VectorMA(c, scale, lm, c);
8438                                                         }
8439                                                 }
8440                                         }
8441                                         c[0] >>= 7;
8442                                         c[1] >>= 7;
8443                                         c[2] >>= 7;
8444                                         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);
8445                                         numvertices++;
8446                                 }
8447                         }
8448                         else
8449                         {
8450                                 for (j = 0;j < surfacenumvertices;j++)
8451                                 {
8452                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8453                                         numvertices++;
8454                                 }
8455                         }
8456                 }
8457         }
8458
8459         // if vertices are deformed (sprite flares and things in maps, possibly
8460         // water waves, bulges and other deformations), modify the copied vertices
8461         // in place
8462         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8463         {
8464                 switch (deform->deform)
8465                 {
8466                 default:
8467                 case Q3DEFORM_PROJECTIONSHADOW:
8468                 case Q3DEFORM_TEXT0:
8469                 case Q3DEFORM_TEXT1:
8470                 case Q3DEFORM_TEXT2:
8471                 case Q3DEFORM_TEXT3:
8472                 case Q3DEFORM_TEXT4:
8473                 case Q3DEFORM_TEXT5:
8474                 case Q3DEFORM_TEXT6:
8475                 case Q3DEFORM_TEXT7:
8476                 case Q3DEFORM_NONE:
8477                         break;
8478                 case Q3DEFORM_AUTOSPRITE:
8479                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8480                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8481                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8482                         VectorNormalize(newforward);
8483                         VectorNormalize(newright);
8484                         VectorNormalize(newup);
8485 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8486 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8487 //                      rsurface.batchvertex3f_bufferoffset = 0;
8488 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8489 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8490 //                      rsurface.batchsvector3f_bufferoffset = 0;
8491 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8492 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8493 //                      rsurface.batchtvector3f_bufferoffset = 0;
8494 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8495 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8496 //                      rsurface.batchnormal3f_bufferoffset = 0;
8497                         // a single autosprite surface can contain multiple sprites...
8498                         for (j = 0;j < batchnumvertices - 3;j += 4)
8499                         {
8500                                 VectorClear(center);
8501                                 for (i = 0;i < 4;i++)
8502                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8503                                 VectorScale(center, 0.25f, center);
8504                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8505                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8506                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8507                                 for (i = 0;i < 4;i++)
8508                                 {
8509                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8510                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8511                                 }
8512                         }
8513                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8514                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8515                         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);
8516                         break;
8517                 case Q3DEFORM_AUTOSPRITE2:
8518                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8519                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8520                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8521                         VectorNormalize(newforward);
8522                         VectorNormalize(newright);
8523                         VectorNormalize(newup);
8524 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8525 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8526 //                      rsurface.batchvertex3f_bufferoffset = 0;
8527                         {
8528                                 const float *v1, *v2;
8529                                 vec3_t start, end;
8530                                 float f, l;
8531                                 struct
8532                                 {
8533                                         float length2;
8534                                         const float *v1;
8535                                         const float *v2;
8536                                 }
8537                                 shortest[2];
8538                                 memset(shortest, 0, sizeof(shortest));
8539                                 // a single autosprite surface can contain multiple sprites...
8540                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8541                                 {
8542                                         VectorClear(center);
8543                                         for (i = 0;i < 4;i++)
8544                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8545                                         VectorScale(center, 0.25f, center);
8546                                         // find the two shortest edges, then use them to define the
8547                                         // axis vectors for rotating around the central axis
8548                                         for (i = 0;i < 6;i++)
8549                                         {
8550                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8551                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8552                                                 l = VectorDistance2(v1, v2);
8553                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8554                                                 if (v1[2] != v2[2])
8555                                                         l += (1.0f / 1024.0f);
8556                                                 if (shortest[0].length2 > l || i == 0)
8557                                                 {
8558                                                         shortest[1] = shortest[0];
8559                                                         shortest[0].length2 = l;
8560                                                         shortest[0].v1 = v1;
8561                                                         shortest[0].v2 = v2;
8562                                                 }
8563                                                 else if (shortest[1].length2 > l || i == 1)
8564                                                 {
8565                                                         shortest[1].length2 = l;
8566                                                         shortest[1].v1 = v1;
8567                                                         shortest[1].v2 = v2;
8568                                                 }
8569                                         }
8570                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8571                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8572                                         // this calculates the right vector from the shortest edge
8573                                         // and the up vector from the edge midpoints
8574                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8575                                         VectorNormalize(right);
8576                                         VectorSubtract(end, start, up);
8577                                         VectorNormalize(up);
8578                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8579                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8580                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8581                                         VectorNegate(forward, forward);
8582                                         VectorReflect(forward, 0, up, forward);
8583                                         VectorNormalize(forward);
8584                                         CrossProduct(up, forward, newright);
8585                                         VectorNormalize(newright);
8586                                         // rotate the quad around the up axis vector, this is made
8587                                         // especially easy by the fact we know the quad is flat,
8588                                         // so we only have to subtract the center position and
8589                                         // measure distance along the right vector, and then
8590                                         // multiply that by the newright vector and add back the
8591                                         // center position
8592                                         // we also need to subtract the old position to undo the
8593                                         // displacement from the center, which we do with a
8594                                         // DotProduct, the subtraction/addition of center is also
8595                                         // optimized into DotProducts here
8596                                         l = DotProduct(right, center);
8597                                         for (i = 0;i < 4;i++)
8598                                         {
8599                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8600                                                 f = DotProduct(right, v1) - l;
8601                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8602                                         }
8603                                 }
8604                         }
8605                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8606                         {
8607 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8608 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8609 //                              rsurface.batchnormal3f_bufferoffset = 0;
8610                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8611                         }
8612                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8613                         {
8614 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8615 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8616 //                              rsurface.batchsvector3f_bufferoffset = 0;
8617 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8618 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8619 //                              rsurface.batchtvector3f_bufferoffset = 0;
8620                                 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);
8621                         }
8622                         break;
8623                 case Q3DEFORM_NORMAL:
8624                         // deform the normals to make reflections wavey
8625                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8626                         rsurface.batchnormal3f_vertexbuffer = NULL;
8627                         rsurface.batchnormal3f_bufferoffset = 0;
8628                         for (j = 0;j < batchnumvertices;j++)
8629                         {
8630                                 float vertex[3];
8631                                 float *normal = rsurface.batchnormal3f + 3*j;
8632                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8633                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8634                                 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]);
8635                                 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]);
8636                                 VectorNormalize(normal);
8637                         }
8638                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8639                         {
8640 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8641 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8642 //                              rsurface.batchsvector3f_bufferoffset = 0;
8643 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8644 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8645 //                              rsurface.batchtvector3f_bufferoffset = 0;
8646                                 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);
8647                         }
8648                         break;
8649                 case Q3DEFORM_WAVE:
8650                         // deform vertex array to make wavey water and flags and such
8651                         waveparms[0] = deform->waveparms[0];
8652                         waveparms[1] = deform->waveparms[1];
8653                         waveparms[2] = deform->waveparms[2];
8654                         waveparms[3] = deform->waveparms[3];
8655                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8656                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8657                         // this is how a divisor of vertex influence on deformation
8658                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8659                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8660 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8661 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8662 //                      rsurface.batchvertex3f_bufferoffset = 0;
8663 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8664 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8665 //                      rsurface.batchnormal3f_bufferoffset = 0;
8666                         for (j = 0;j < batchnumvertices;j++)
8667                         {
8668                                 // if the wavefunc depends on time, evaluate it per-vertex
8669                                 if (waveparms[3])
8670                                 {
8671                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8672                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8673                                 }
8674                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8675                         }
8676                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8677                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8678                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8679                         {
8680 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8681 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8682 //                              rsurface.batchsvector3f_bufferoffset = 0;
8683 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8684 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8685 //                              rsurface.batchtvector3f_bufferoffset = 0;
8686                                 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);
8687                         }
8688                         break;
8689                 case Q3DEFORM_BULGE:
8690                         // deform vertex array to make the surface have moving bulges
8691 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8692 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8693 //                      rsurface.batchvertex3f_bufferoffset = 0;
8694 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8695 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8696 //                      rsurface.batchnormal3f_bufferoffset = 0;
8697                         for (j = 0;j < batchnumvertices;j++)
8698                         {
8699                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8700                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8701                         }
8702                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8703                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8704                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8705                         {
8706 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8707 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8708 //                              rsurface.batchsvector3f_bufferoffset = 0;
8709 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8710 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8711 //                              rsurface.batchtvector3f_bufferoffset = 0;
8712                                 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);
8713                         }
8714                         break;
8715                 case Q3DEFORM_MOVE:
8716                         // deform vertex array
8717                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8718                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8719                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8720                         VectorScale(deform->parms, scale, waveparms);
8721 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8722 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8723 //                      rsurface.batchvertex3f_bufferoffset = 0;
8724                         for (j = 0;j < batchnumvertices;j++)
8725                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8726                         break;
8727                 }
8728         }
8729
8730         // generate texcoords based on the chosen texcoord source
8731         switch(rsurface.texture->tcgen.tcgen)
8732         {
8733         default:
8734         case Q3TCGEN_TEXTURE:
8735                 break;
8736         case Q3TCGEN_LIGHTMAP:
8737 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8738 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8739 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8740                 if (rsurface.batchtexcoordlightmap2f)
8741                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8742                 break;
8743         case Q3TCGEN_VECTOR:
8744 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8745 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8746 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8747                 for (j = 0;j < batchnumvertices;j++)
8748                 {
8749                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8750                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8751                 }
8752                 break;
8753         case Q3TCGEN_ENVIRONMENT:
8754                 // make environment reflections using a spheremap
8755                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8756                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8757                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8758                 for (j = 0;j < batchnumvertices;j++)
8759                 {
8760                         // identical to Q3A's method, but executed in worldspace so
8761                         // carried models can be shiny too
8762
8763                         float viewer[3], d, reflected[3], worldreflected[3];
8764
8765                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8766                         // VectorNormalize(viewer);
8767
8768                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8769
8770                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8771                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8772                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8773                         // note: this is proportinal to viewer, so we can normalize later
8774
8775                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8776                         VectorNormalize(worldreflected);
8777
8778                         // note: this sphere map only uses world x and z!
8779                         // so positive and negative y will LOOK THE SAME.
8780                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8781                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8782                 }
8783                 break;
8784         }
8785         // the only tcmod that needs software vertex processing is turbulent, so
8786         // check for it here and apply the changes if needed
8787         // and we only support that as the first one
8788         // (handling a mixture of turbulent and other tcmods would be problematic
8789         //  without punting it entirely to a software path)
8790         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8791         {
8792                 amplitude = rsurface.texture->tcmods[0].parms[1];
8793                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8794 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8795 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8796 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8797                 for (j = 0;j < batchnumvertices;j++)
8798                 {
8799                         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);
8800                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8801                 }
8802         }
8803
8804         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8805         {
8806                 // convert the modified arrays to vertex structs
8807 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8808 //              rsurface.batchvertexmeshbuffer = NULL;
8809                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8810                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8811                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8812                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8813                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8814                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8815                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8816                 {
8817                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8818                         {
8819                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8820                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8821                         }
8822                 }
8823                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8824                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8825                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8826                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8827                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8828                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8829                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8830                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8831                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8832         }
8833 }
8834
8835 void RSurf_DrawBatch(void)
8836 {
8837         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8838         // through the pipeline, killing it earlier in the pipeline would have
8839         // per-surface overhead rather than per-batch overhead, so it's best to
8840         // reject it here, before it hits glDraw.
8841         if (rsurface.batchnumtriangles == 0)
8842                 return;
8843 #if 0
8844         // batch debugging code
8845         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8846         {
8847                 int i;
8848                 int j;
8849                 int c;
8850                 const int *e;
8851                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8852                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8853                 {
8854                         c = e[i];
8855                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8856                         {
8857                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8858                                 {
8859                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8860                                                 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);
8861                                         break;
8862                                 }
8863                         }
8864                 }
8865         }
8866 #endif
8867         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);
8868 }
8869
8870 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8871 {
8872         // pick the closest matching water plane
8873         int planeindex, vertexindex, bestplaneindex = -1;
8874         float d, bestd;
8875         vec3_t vert;
8876         const float *v;
8877         r_waterstate_waterplane_t *p;
8878         qboolean prepared = false;
8879         bestd = 0;
8880         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8881         {
8882                 if(p->camera_entity != rsurface.texture->camera_entity)
8883                         continue;
8884                 d = 0;
8885                 if(!prepared)
8886                 {
8887                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8888                         prepared = true;
8889                         if(rsurface.batchnumvertices == 0)
8890                                 break;
8891                 }
8892                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8893                 {
8894                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8895                         d += fabs(PlaneDiff(vert, &p->plane));
8896                 }
8897                 if (bestd > d || bestplaneindex < 0)
8898                 {
8899                         bestd = d;
8900                         bestplaneindex = planeindex;
8901                 }
8902         }
8903         return bestplaneindex;
8904         // NOTE: this MAY return a totally unrelated water plane; we can ignore
8905         // this situation though, as it might be better to render single larger
8906         // batches with useless stuff (backface culled for example) than to
8907         // render multiple smaller batches
8908 }
8909
8910 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8911 {
8912         int i;
8913         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8914         rsurface.passcolor4f_vertexbuffer = 0;
8915         rsurface.passcolor4f_bufferoffset = 0;
8916         for (i = 0;i < rsurface.batchnumvertices;i++)
8917                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8918 }
8919
8920 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8921 {
8922         int i;
8923         float f;
8924         const float *v;
8925         const float *c;
8926         float *c2;
8927         if (rsurface.passcolor4f)
8928         {
8929                 // generate color arrays
8930                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8931                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8932                 rsurface.passcolor4f_vertexbuffer = 0;
8933                 rsurface.passcolor4f_bufferoffset = 0;
8934                 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)
8935                 {
8936                         f = RSurf_FogVertex(v);
8937                         c2[0] = c[0] * f;
8938                         c2[1] = c[1] * f;
8939                         c2[2] = c[2] * f;
8940                         c2[3] = c[3];
8941                 }
8942         }
8943         else
8944         {
8945                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8946                 rsurface.passcolor4f_vertexbuffer = 0;
8947                 rsurface.passcolor4f_bufferoffset = 0;
8948                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8949                 {
8950                         f = RSurf_FogVertex(v);
8951                         c2[0] = f;
8952                         c2[1] = f;
8953                         c2[2] = f;
8954                         c2[3] = 1;
8955                 }
8956         }
8957 }
8958
8959 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8960 {
8961         int i;
8962         float f;
8963         const float *v;
8964         const float *c;
8965         float *c2;
8966         if (!rsurface.passcolor4f)
8967                 return;
8968         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8969         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8970         rsurface.passcolor4f_vertexbuffer = 0;
8971         rsurface.passcolor4f_bufferoffset = 0;
8972         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)
8973         {
8974                 f = RSurf_FogVertex(v);
8975                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8976                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8977                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8978                 c2[3] = c[3];
8979         }
8980 }
8981
8982 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
8983 {
8984         int i;
8985         const float *c;
8986         float *c2;
8987         if (!rsurface.passcolor4f)
8988                 return;
8989         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8990         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8991         rsurface.passcolor4f_vertexbuffer = 0;
8992         rsurface.passcolor4f_bufferoffset = 0;
8993         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
8994         {
8995                 c2[0] = c[0] * r;
8996                 c2[1] = c[1] * g;
8997                 c2[2] = c[2] * b;
8998                 c2[3] = c[3] * a;
8999         }
9000 }
9001
9002 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9003 {
9004         int i;
9005         const float *c;
9006         float *c2;
9007         if (!rsurface.passcolor4f)
9008                 return;
9009         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9010         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9011         rsurface.passcolor4f_vertexbuffer = 0;
9012         rsurface.passcolor4f_bufferoffset = 0;
9013         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9014         {
9015                 c2[0] = c[0] + r_refdef.scene.ambient;
9016                 c2[1] = c[1] + r_refdef.scene.ambient;
9017                 c2[2] = c[2] + r_refdef.scene.ambient;
9018                 c2[3] = c[3];
9019         }
9020 }
9021
9022 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9023 {
9024         // TODO: optimize
9025         rsurface.passcolor4f = NULL;
9026         rsurface.passcolor4f_vertexbuffer = 0;
9027         rsurface.passcolor4f_bufferoffset = 0;
9028         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9029         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9030         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9031         GL_Color(r, g, b, a);
9032         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9033         RSurf_DrawBatch();
9034 }
9035
9036 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9037 {
9038         // TODO: optimize applyfog && applycolor case
9039         // just apply fog if necessary, and tint the fog color array if necessary
9040         rsurface.passcolor4f = NULL;
9041         rsurface.passcolor4f_vertexbuffer = 0;
9042         rsurface.passcolor4f_bufferoffset = 0;
9043         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9044         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9045         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9046         GL_Color(r, g, b, a);
9047         RSurf_DrawBatch();
9048 }
9049
9050 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9051 {
9052         // TODO: optimize
9053         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9054         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9055         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9056         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9057         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9058         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9059         GL_Color(r, g, b, a);
9060         RSurf_DrawBatch();
9061 }
9062
9063 static void RSurf_DrawBatch_GL11_ClampColor(void)
9064 {
9065         int i;
9066         const float *c1;
9067         float *c2;
9068         if (!rsurface.passcolor4f)
9069                 return;
9070         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9071         {
9072                 c2[0] = bound(0.0f, c1[0], 1.0f);
9073                 c2[1] = bound(0.0f, c1[1], 1.0f);
9074                 c2[2] = bound(0.0f, c1[2], 1.0f);
9075                 c2[3] = bound(0.0f, c1[3], 1.0f);
9076         }
9077 }
9078
9079 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9080 {
9081         int i;
9082         float f;
9083         const float *v;
9084         const float *n;
9085         float *c;
9086         //vec3_t eyedir;
9087
9088         // fake shading
9089         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9090         rsurface.passcolor4f_vertexbuffer = 0;
9091         rsurface.passcolor4f_bufferoffset = 0;
9092         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
9093         {
9094                 f = -DotProduct(r_refdef.view.forward, n);
9095                 f = max(0, f);
9096                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9097                 f *= r_refdef.lightmapintensity;
9098                 Vector4Set(c, f, f, f, 1);
9099         }
9100 }
9101
9102 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9103 {
9104         RSurf_DrawBatch_GL11_ApplyFakeLight();
9105         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9106         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9107         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9108         GL_Color(r, g, b, a);
9109         RSurf_DrawBatch();
9110 }
9111
9112 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9113 {
9114         int i;
9115         float f;
9116         float alpha;
9117         const float *v;
9118         const float *n;
9119         float *c;
9120         vec3_t ambientcolor;
9121         vec3_t diffusecolor;
9122         vec3_t lightdir;
9123         // TODO: optimize
9124         // model lighting
9125         VectorCopy(rsurface.modellight_lightdir, lightdir);
9126         f = 0.5f * r_refdef.lightmapintensity;
9127         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9128         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9129         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9130         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9131         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9132         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9133         alpha = *a;
9134         if (VectorLength2(diffusecolor) > 0)
9135         {
9136                 // q3-style directional shading
9137                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9138                 rsurface.passcolor4f_vertexbuffer = 0;
9139                 rsurface.passcolor4f_bufferoffset = 0;
9140                 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)
9141                 {
9142                         if ((f = DotProduct(n, lightdir)) > 0)
9143                                 VectorMA(ambientcolor, f, diffusecolor, c);
9144                         else
9145                                 VectorCopy(ambientcolor, c);
9146                         c[3] = alpha;
9147                 }
9148                 *r = 1;
9149                 *g = 1;
9150                 *b = 1;
9151                 *a = 1;
9152                 *applycolor = false;
9153         }
9154         else
9155         {
9156                 *r = ambientcolor[0];
9157                 *g = ambientcolor[1];
9158                 *b = ambientcolor[2];
9159                 rsurface.passcolor4f = NULL;
9160                 rsurface.passcolor4f_vertexbuffer = 0;
9161                 rsurface.passcolor4f_bufferoffset = 0;
9162         }
9163 }
9164
9165 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9166 {
9167         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9168         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9169         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9170         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9171         GL_Color(r, g, b, a);
9172         RSurf_DrawBatch();
9173 }
9174
9175 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9176 {
9177         int i;
9178         float f;
9179         const float *v;
9180         float *c;
9181         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9182         {
9183                 f = 1 - RSurf_FogVertex(v);
9184                 c[0] = r;
9185                 c[1] = g;
9186                 c[2] = b;
9187                 c[3] = f * a;
9188         }
9189 }
9190
9191 void RSurf_SetupDepthAndCulling(void)
9192 {
9193         // submodels are biased to avoid z-fighting with world surfaces that they
9194         // may be exactly overlapping (avoids z-fighting artifacts on certain
9195         // doors and things in Quake maps)
9196         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9197         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9198         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9199         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9200 }
9201
9202 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9203 {
9204         // transparent sky would be ridiculous
9205         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9206                 return;
9207         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9208         skyrenderlater = true;
9209         RSurf_SetupDepthAndCulling();
9210         GL_DepthMask(true);
9211         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9212         // skymasking on them, and Quake3 never did sky masking (unlike
9213         // software Quake and software Quake2), so disable the sky masking
9214         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9215         // and skymasking also looks very bad when noclipping outside the
9216         // level, so don't use it then either.
9217         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9218         {
9219                 R_Mesh_ResetTextureState();
9220                 if (skyrendermasked)
9221                 {
9222                         R_SetupShader_DepthOrShadow();
9223                         // depth-only (masking)
9224                         GL_ColorMask(0,0,0,0);
9225                         // just to make sure that braindead drivers don't draw
9226                         // anything despite that colormask...
9227                         GL_BlendFunc(GL_ZERO, GL_ONE);
9228                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9229                         if (rsurface.batchvertex3fbuffer)
9230                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9231                         else
9232                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9233                 }
9234                 else
9235                 {
9236                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9237                         // fog sky
9238                         GL_BlendFunc(GL_ONE, GL_ZERO);
9239                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9240                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9241                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9242                 }
9243                 RSurf_DrawBatch();
9244                 if (skyrendermasked)
9245                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9246         }
9247         R_Mesh_ResetTextureState();
9248         GL_Color(1, 1, 1, 1);
9249 }
9250
9251 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9252 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9253 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9254 {
9255         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9256                 return;
9257         if (prepass)
9258         {
9259                 // render screenspace normalmap to texture
9260                 GL_DepthMask(true);
9261                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9262                 RSurf_DrawBatch();
9263                 return;
9264         }
9265
9266         // bind lightmap texture
9267
9268         // water/refraction/reflection/camera surfaces have to be handled specially
9269         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9270         {
9271                 int start, end, startplaneindex;
9272                 for (start = 0;start < texturenumsurfaces;start = end)
9273                 {
9274                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9275                         if(startplaneindex < 0)
9276                         {
9277                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9278                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9279                                 end = start + 1;
9280                                 continue;
9281                         }
9282                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9283                                 ;
9284                         // now that we have a batch using the same planeindex, render it
9285                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9286                         {
9287                                 // render water or distortion background
9288                                 GL_DepthMask(true);
9289                                 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));
9290                                 RSurf_DrawBatch();
9291                                 // blend surface on top
9292                                 GL_DepthMask(false);
9293                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9294                                 RSurf_DrawBatch();
9295                         }
9296                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9297                         {
9298                                 // render surface with reflection texture as input
9299                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9300                                 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));
9301                                 RSurf_DrawBatch();
9302                         }
9303                 }
9304                 return;
9305         }
9306
9307         // render surface batch normally
9308         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9309         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9310         RSurf_DrawBatch();
9311 }
9312
9313 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9314 {
9315         // OpenGL 1.3 path - anything not completely ancient
9316         qboolean applycolor;
9317         qboolean applyfog;
9318         int layerindex;
9319         const texturelayer_t *layer;
9320         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);
9321         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9322
9323         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9324         {
9325                 vec4_t layercolor;
9326                 int layertexrgbscale;
9327                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9328                 {
9329                         if (layerindex == 0)
9330                                 GL_AlphaTest(true);
9331                         else
9332                         {
9333                                 GL_AlphaTest(false);
9334                                 GL_DepthFunc(GL_EQUAL);
9335                         }
9336                 }
9337                 GL_DepthMask(layer->depthmask && writedepth);
9338                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9339                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9340                 {
9341                         layertexrgbscale = 4;
9342                         VectorScale(layer->color, 0.25f, layercolor);
9343                 }
9344                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9345                 {
9346                         layertexrgbscale = 2;
9347                         VectorScale(layer->color, 0.5f, layercolor);
9348                 }
9349                 else
9350                 {
9351                         layertexrgbscale = 1;
9352                         VectorScale(layer->color, 1.0f, layercolor);
9353                 }
9354                 layercolor[3] = layer->color[3];
9355                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9356                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9357                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9358                 switch (layer->type)
9359                 {
9360                 case TEXTURELAYERTYPE_LITTEXTURE:
9361                         // single-pass lightmapped texture with 2x rgbscale
9362                         R_Mesh_TexBind(0, r_texture_white);
9363                         R_Mesh_TexMatrix(0, NULL);
9364                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9365                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9366                         R_Mesh_TexBind(1, layer->texture);
9367                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9368                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9369                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9370                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9371                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9372                         else if (FAKELIGHT_ENABLED)
9373                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9374                         else if (rsurface.uselightmaptexture)
9375                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9376                         else
9377                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9378                         break;
9379                 case TEXTURELAYERTYPE_TEXTURE:
9380                         // singletexture unlit texture with transparency support
9381                         R_Mesh_TexBind(0, layer->texture);
9382                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9383                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9384                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9385                         R_Mesh_TexBind(1, 0);
9386                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9387                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9388                         break;
9389                 case TEXTURELAYERTYPE_FOG:
9390                         // singletexture fogging
9391                         if (layer->texture)
9392                         {
9393                                 R_Mesh_TexBind(0, layer->texture);
9394                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9395                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9396                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9397                         }
9398                         else
9399                         {
9400                                 R_Mesh_TexBind(0, 0);
9401                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9402                         }
9403                         R_Mesh_TexBind(1, 0);
9404                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9405                         // generate a color array for the fog pass
9406                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9407                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9408                         RSurf_DrawBatch();
9409                         break;
9410                 default:
9411                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9412                 }
9413         }
9414         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9415         {
9416                 GL_DepthFunc(GL_LEQUAL);
9417                 GL_AlphaTest(false);
9418         }
9419 }
9420
9421 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9422 {
9423         // OpenGL 1.1 - crusty old voodoo path
9424         qboolean applyfog;
9425         int layerindex;
9426         const texturelayer_t *layer;
9427         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);
9428         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9429
9430         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9431         {
9432                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9433                 {
9434                         if (layerindex == 0)
9435                                 GL_AlphaTest(true);
9436                         else
9437                         {
9438                                 GL_AlphaTest(false);
9439                                 GL_DepthFunc(GL_EQUAL);
9440                         }
9441                 }
9442                 GL_DepthMask(layer->depthmask && writedepth);
9443                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9444                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9445                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9446                 switch (layer->type)
9447                 {
9448                 case TEXTURELAYERTYPE_LITTEXTURE:
9449                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9450                         {
9451                                 // two-pass lit texture with 2x rgbscale
9452                                 // first the lightmap pass
9453                                 R_Mesh_TexBind(0, r_texture_white);
9454                                 R_Mesh_TexMatrix(0, NULL);
9455                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9456                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9457                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9458                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9459                                 else if (FAKELIGHT_ENABLED)
9460                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9461                                 else if (rsurface.uselightmaptexture)
9462                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9463                                 else
9464                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9465                                 // then apply the texture to it
9466                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9467                                 R_Mesh_TexBind(0, layer->texture);
9468                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9469                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9470                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9471                                 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);
9472                         }
9473                         else
9474                         {
9475                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9476                                 R_Mesh_TexBind(0, layer->texture);
9477                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9478                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9479                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9480                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9481                                         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);
9482                                 else
9483                                         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);
9484                         }
9485                         break;
9486                 case TEXTURELAYERTYPE_TEXTURE:
9487                         // singletexture unlit texture with transparency support
9488                         R_Mesh_TexBind(0, layer->texture);
9489                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9490                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9491                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9492                         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);
9493                         break;
9494                 case TEXTURELAYERTYPE_FOG:
9495                         // singletexture fogging
9496                         if (layer->texture)
9497                         {
9498                                 R_Mesh_TexBind(0, layer->texture);
9499                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9500                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9501                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9502                         }
9503                         else
9504                         {
9505                                 R_Mesh_TexBind(0, 0);
9506                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9507                         }
9508                         // generate a color array for the fog pass
9509                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9510                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9511                         RSurf_DrawBatch();
9512                         break;
9513                 default:
9514                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9515                 }
9516         }
9517         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9518         {
9519                 GL_DepthFunc(GL_LEQUAL);
9520                 GL_AlphaTest(false);
9521         }
9522 }
9523
9524 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9525 {
9526         int vi;
9527         int j;
9528         r_vertexgeneric_t *batchvertex;
9529         float c[4];
9530
9531 //      R_Mesh_ResetTextureState();
9532         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9533
9534         if(rsurface.texture && rsurface.texture->currentskinframe)
9535         {
9536                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9537                 c[3] *= rsurface.texture->currentalpha;
9538         }
9539         else
9540         {
9541                 c[0] = 1;
9542                 c[1] = 0;
9543                 c[2] = 1;
9544                 c[3] = 1;
9545         }
9546
9547         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9548         {
9549                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9550                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9551                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9552         }
9553
9554         // brighten it up (as texture value 127 means "unlit")
9555         c[0] *= 2 * r_refdef.view.colorscale;
9556         c[1] *= 2 * r_refdef.view.colorscale;
9557         c[2] *= 2 * r_refdef.view.colorscale;
9558
9559         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9560                 c[3] *= r_wateralpha.value;
9561
9562         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9563         {
9564                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9565                 GL_DepthMask(false);
9566         }
9567         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9568         {
9569                 GL_BlendFunc(GL_ONE, GL_ONE);
9570                 GL_DepthMask(false);
9571         }
9572         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9573         {
9574                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9575                 GL_DepthMask(false);
9576         }
9577         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9578         {
9579                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9580                 GL_DepthMask(false);
9581         }
9582         else
9583         {
9584                 GL_BlendFunc(GL_ONE, GL_ZERO);
9585                 GL_DepthMask(writedepth);
9586         }
9587
9588         if (r_showsurfaces.integer == 3)
9589         {
9590                 rsurface.passcolor4f = NULL;
9591
9592                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9593                 {
9594                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9595
9596                         rsurface.passcolor4f = NULL;
9597                         rsurface.passcolor4f_vertexbuffer = 0;
9598                         rsurface.passcolor4f_bufferoffset = 0;
9599                 }
9600                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9601                 {
9602                         qboolean applycolor = true;
9603                         float one = 1.0;
9604
9605                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9606
9607                         r_refdef.lightmapintensity = 1;
9608                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9609                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9610                 }
9611                 else if (FAKELIGHT_ENABLED)
9612                 {
9613                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9614
9615                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9616                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9617                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9618                 }
9619                 else
9620                 {
9621                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9622
9623                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9624                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9625                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9626                 }
9627
9628                 if(!rsurface.passcolor4f)
9629                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9630
9631                 RSurf_DrawBatch_GL11_ApplyAmbient();
9632                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9633                 if(r_refdef.fogenabled)
9634                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9635                 RSurf_DrawBatch_GL11_ClampColor();
9636
9637                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9638                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9639                 RSurf_DrawBatch();
9640         }
9641         else if (!r_refdef.view.showdebug)
9642         {
9643                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9644                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9645                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9646                 {
9647                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9648                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9649                 }
9650                 R_Mesh_PrepareVertices_Generic_Unlock();
9651                 RSurf_DrawBatch();
9652         }
9653         else if (r_showsurfaces.integer == 4)
9654         {
9655                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9656                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9657                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9658                 {
9659                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9660                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9661                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9662                 }
9663                 R_Mesh_PrepareVertices_Generic_Unlock();
9664                 RSurf_DrawBatch();
9665         }
9666         else if (r_showsurfaces.integer == 2)
9667         {
9668                 const int *e;
9669                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9670                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9671                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9672                 {
9673                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9674                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9675                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9676                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9677                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9678                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9679                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9680                 }
9681                 R_Mesh_PrepareVertices_Generic_Unlock();
9682                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9683         }
9684         else
9685         {
9686                 int texturesurfaceindex;
9687                 int k;
9688                 const msurface_t *surface;
9689                 float surfacecolor4f[4];
9690                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9691                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9692                 vi = 0;
9693                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9694                 {
9695                         surface = texturesurfacelist[texturesurfaceindex];
9696                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9697                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9698                         for (j = 0;j < surface->num_vertices;j++)
9699                         {
9700                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9701                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9702                                 vi++;
9703                         }
9704                 }
9705                 R_Mesh_PrepareVertices_Generic_Unlock();
9706                 RSurf_DrawBatch();
9707         }
9708 }
9709
9710 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9711 {
9712         CHECKGLERROR
9713         RSurf_SetupDepthAndCulling();
9714         if (r_showsurfaces.integer)
9715         {
9716                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9717                 return;
9718         }
9719         switch (vid.renderpath)
9720         {
9721         case RENDERPATH_GL20:
9722         case RENDERPATH_D3D9:
9723         case RENDERPATH_D3D10:
9724         case RENDERPATH_D3D11:
9725         case RENDERPATH_SOFT:
9726         case RENDERPATH_GLES2:
9727                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9728                 break;
9729         case RENDERPATH_GL13:
9730                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9731                 break;
9732         case RENDERPATH_GL11:
9733                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9734                 break;
9735         }
9736         CHECKGLERROR
9737 }
9738
9739 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9740 {
9741         CHECKGLERROR
9742         RSurf_SetupDepthAndCulling();
9743         if (r_showsurfaces.integer)
9744         {
9745                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9746                 return;
9747         }
9748         switch (vid.renderpath)
9749         {
9750         case RENDERPATH_GL20:
9751         case RENDERPATH_D3D9:
9752         case RENDERPATH_D3D10:
9753         case RENDERPATH_D3D11:
9754         case RENDERPATH_SOFT:
9755         case RENDERPATH_GLES2:
9756                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9757                 break;
9758         case RENDERPATH_GL13:
9759                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9760                 break;
9761         case RENDERPATH_GL11:
9762                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9763                 break;
9764         }
9765         CHECKGLERROR
9766 }
9767
9768 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9769 {
9770         int i, j;
9771         int texturenumsurfaces, endsurface;
9772         texture_t *texture;
9773         const msurface_t *surface;
9774 #define MAXBATCH_TRANSPARENTSURFACES 256
9775         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9776
9777         // if the model is static it doesn't matter what value we give for
9778         // wantnormals and wanttangents, so this logic uses only rules applicable
9779         // to a model, knowing that they are meaningless otherwise
9780         if (ent == r_refdef.scene.worldentity)
9781                 RSurf_ActiveWorldEntity();
9782         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9783                 RSurf_ActiveModelEntity(ent, false, false, false);
9784         else
9785         {
9786                 switch (vid.renderpath)
9787                 {
9788                 case RENDERPATH_GL20:
9789                 case RENDERPATH_D3D9:
9790                 case RENDERPATH_D3D10:
9791                 case RENDERPATH_D3D11:
9792                 case RENDERPATH_SOFT:
9793                 case RENDERPATH_GLES2:
9794                         RSurf_ActiveModelEntity(ent, true, true, false);
9795                         break;
9796                 case RENDERPATH_GL13:
9797                 case RENDERPATH_GL11:
9798                         RSurf_ActiveModelEntity(ent, true, false, false);
9799                         break;
9800                 }
9801         }
9802
9803         if (r_transparentdepthmasking.integer)
9804         {
9805                 qboolean setup = false;
9806                 for (i = 0;i < numsurfaces;i = j)
9807                 {
9808                         j = i + 1;
9809                         surface = rsurface.modelsurfaces + surfacelist[i];
9810                         texture = surface->texture;
9811                         rsurface.texture = R_GetCurrentTexture(texture);
9812                         rsurface.lightmaptexture = NULL;
9813                         rsurface.deluxemaptexture = NULL;
9814                         rsurface.uselightmaptexture = false;
9815                         // scan ahead until we find a different texture
9816                         endsurface = min(i + 1024, numsurfaces);
9817                         texturenumsurfaces = 0;
9818                         texturesurfacelist[texturenumsurfaces++] = surface;
9819                         for (;j < endsurface;j++)
9820                         {
9821                                 surface = rsurface.modelsurfaces + surfacelist[j];
9822                                 if (texture != surface->texture)
9823                                         break;
9824                                 texturesurfacelist[texturenumsurfaces++] = surface;
9825                         }
9826                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9827                                 continue;
9828                         // render the range of surfaces as depth
9829                         if (!setup)
9830                         {
9831                                 setup = true;
9832                                 GL_ColorMask(0,0,0,0);
9833                                 GL_Color(1,1,1,1);
9834                                 GL_DepthTest(true);
9835                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9836                                 GL_DepthMask(true);
9837 //                              R_Mesh_ResetTextureState();
9838                                 R_SetupShader_DepthOrShadow();
9839                         }
9840                         RSurf_SetupDepthAndCulling();
9841                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9842                         if (rsurface.batchvertex3fbuffer)
9843                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9844                         else
9845                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9846                         RSurf_DrawBatch();
9847                 }
9848                 if (setup)
9849                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9850         }
9851
9852         for (i = 0;i < numsurfaces;i = j)
9853         {
9854                 j = i + 1;
9855                 surface = rsurface.modelsurfaces + surfacelist[i];
9856                 texture = surface->texture;
9857                 rsurface.texture = R_GetCurrentTexture(texture);
9858                 // scan ahead until we find a different texture
9859                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9860                 texturenumsurfaces = 0;
9861                 texturesurfacelist[texturenumsurfaces++] = surface;
9862                 if(FAKELIGHT_ENABLED)
9863                 {
9864                         rsurface.lightmaptexture = NULL;
9865                         rsurface.deluxemaptexture = NULL;
9866                         rsurface.uselightmaptexture = false;
9867                         for (;j < endsurface;j++)
9868                         {
9869                                 surface = rsurface.modelsurfaces + surfacelist[j];
9870                                 if (texture != surface->texture)
9871                                         break;
9872                                 texturesurfacelist[texturenumsurfaces++] = surface;
9873                         }
9874                 }
9875                 else
9876                 {
9877                         rsurface.lightmaptexture = surface->lightmaptexture;
9878                         rsurface.deluxemaptexture = surface->deluxemaptexture;
9879                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9880                         for (;j < endsurface;j++)
9881                         {
9882                                 surface = rsurface.modelsurfaces + surfacelist[j];
9883                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9884                                         break;
9885                                 texturesurfacelist[texturenumsurfaces++] = surface;
9886                         }
9887                 }
9888                 // render the range of surfaces
9889                 if (ent == r_refdef.scene.worldentity)
9890                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9891                 else
9892                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9893         }
9894         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9895 }
9896
9897 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9898 {
9899         // transparent surfaces get pushed off into the transparent queue
9900         int surfacelistindex;
9901         const msurface_t *surface;
9902         vec3_t tempcenter, center;
9903         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9904         {
9905                 surface = texturesurfacelist[surfacelistindex];
9906                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9907                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9908                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9909                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9910                 if (queueentity->transparent_offset) // transparent offset
9911                 {
9912                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9913                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9914                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9915                 }
9916                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9917         }
9918 }
9919
9920 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9921 {
9922         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9923                 return;
9924         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9925                 return;
9926         RSurf_SetupDepthAndCulling();
9927         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9928         if (rsurface.batchvertex3fbuffer)
9929                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9930         else
9931                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9932         RSurf_DrawBatch();
9933 }
9934
9935 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9936 {
9937         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9938         CHECKGLERROR
9939         if (depthonly)
9940                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9941         else if (prepass)
9942         {
9943                 if (!rsurface.texture->currentnumlayers)
9944                         return;
9945                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9946                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9947                 else
9948                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9949         }
9950         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9951                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9952         else if (!rsurface.texture->currentnumlayers)
9953                 return;
9954         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9955         {
9956                 // in the deferred case, transparent surfaces were queued during prepass
9957                 if (!r_shadow_usingdeferredprepass)
9958                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9959         }
9960         else
9961         {
9962                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9963                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9964         }
9965         CHECKGLERROR
9966 }
9967
9968 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9969 {
9970         int i, j;
9971         texture_t *texture;
9972         R_FrameData_SetMark();
9973         // break the surface list down into batches by texture and use of lightmapping
9974         for (i = 0;i < numsurfaces;i = j)
9975         {
9976                 j = i + 1;
9977                 // texture is the base texture pointer, rsurface.texture is the
9978                 // current frame/skin the texture is directing us to use (for example
9979                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9980                 // use skin 1 instead)
9981                 texture = surfacelist[i]->texture;
9982                 rsurface.texture = R_GetCurrentTexture(texture);
9983                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9984                 {
9985                         // if this texture is not the kind we want, skip ahead to the next one
9986                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9987                                 ;
9988                         continue;
9989                 }
9990                 if(FAKELIGHT_ENABLED || depthonly || prepass)
9991                 {
9992                         rsurface.lightmaptexture = NULL;
9993                         rsurface.deluxemaptexture = NULL;
9994                         rsurface.uselightmaptexture = false;
9995                         // simply scan ahead until we find a different texture or lightmap state
9996                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9997                                 ;
9998                 }
9999                 else
10000                 {
10001                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10002                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10003                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10004                         // simply scan ahead until we find a different texture or lightmap state
10005                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10006                                 ;
10007                 }
10008                 // render the range of surfaces
10009                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10010         }
10011         R_FrameData_ReturnToMark();
10012 }
10013
10014 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10015 {
10016         CHECKGLERROR
10017         if (depthonly)
10018                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10019         else if (prepass)
10020         {
10021                 if (!rsurface.texture->currentnumlayers)
10022                         return;
10023                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10024                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10025                 else
10026                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10027         }
10028         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10029                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10030         else if (!rsurface.texture->currentnumlayers)
10031                 return;
10032         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10033         {
10034                 // in the deferred case, transparent surfaces were queued during prepass
10035                 if (!r_shadow_usingdeferredprepass)
10036                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10037         }
10038         else
10039         {
10040                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10041                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10042         }
10043         CHECKGLERROR
10044 }
10045
10046 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10047 {
10048         int i, j;
10049         texture_t *texture;
10050         R_FrameData_SetMark();
10051         // break the surface list down into batches by texture and use of lightmapping
10052         for (i = 0;i < numsurfaces;i = j)
10053         {
10054                 j = i + 1;
10055                 // texture is the base texture pointer, rsurface.texture is the
10056                 // current frame/skin the texture is directing us to use (for example
10057                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10058                 // use skin 1 instead)
10059                 texture = surfacelist[i]->texture;
10060                 rsurface.texture = R_GetCurrentTexture(texture);
10061                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10062                 {
10063                         // if this texture is not the kind we want, skip ahead to the next one
10064                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10065                                 ;
10066                         continue;
10067                 }
10068                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10069                 {
10070                         rsurface.lightmaptexture = NULL;
10071                         rsurface.deluxemaptexture = NULL;
10072                         rsurface.uselightmaptexture = false;
10073                         // simply scan ahead until we find a different texture or lightmap state
10074                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10075                                 ;
10076                 }
10077                 else
10078                 {
10079                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10080                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10081                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10082                         // simply scan ahead until we find a different texture or lightmap state
10083                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10084                                 ;
10085                 }
10086                 // render the range of surfaces
10087                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10088         }
10089         R_FrameData_ReturnToMark();
10090 }
10091
10092 float locboxvertex3f[6*4*3] =
10093 {
10094         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10095         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10096         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10097         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10098         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10099         1,0,0, 0,0,0, 0,1,0, 1,1,0
10100 };
10101
10102 unsigned short locboxelements[6*2*3] =
10103 {
10104          0, 1, 2, 0, 2, 3,
10105          4, 5, 6, 4, 6, 7,
10106          8, 9,10, 8,10,11,
10107         12,13,14, 12,14,15,
10108         16,17,18, 16,18,19,
10109         20,21,22, 20,22,23
10110 };
10111
10112 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10113 {
10114         int i, j;
10115         cl_locnode_t *loc = (cl_locnode_t *)ent;
10116         vec3_t mins, size;
10117         float vertex3f[6*4*3];
10118         CHECKGLERROR
10119         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10120         GL_DepthMask(false);
10121         GL_DepthRange(0, 1);
10122         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10123         GL_DepthTest(true);
10124         GL_CullFace(GL_NONE);
10125         R_EntityMatrix(&identitymatrix);
10126
10127 //      R_Mesh_ResetTextureState();
10128
10129         i = surfacelist[0];
10130         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10131                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10132                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10133                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10134
10135         if (VectorCompare(loc->mins, loc->maxs))
10136         {
10137                 VectorSet(size, 2, 2, 2);
10138                 VectorMA(loc->mins, -0.5f, size, mins);
10139         }
10140         else
10141         {
10142                 VectorCopy(loc->mins, mins);
10143                 VectorSubtract(loc->maxs, loc->mins, size);
10144         }
10145
10146         for (i = 0;i < 6*4*3;)
10147                 for (j = 0;j < 3;j++, i++)
10148                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10149
10150         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10151         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10152         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10153 }
10154
10155 void R_DrawLocs(void)
10156 {
10157         int index;
10158         cl_locnode_t *loc, *nearestloc;
10159         vec3_t center;
10160         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10161         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10162         {
10163                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10164                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10165         }
10166 }
10167
10168 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10169 {
10170         if (decalsystem->decals)
10171                 Mem_Free(decalsystem->decals);
10172         memset(decalsystem, 0, sizeof(*decalsystem));
10173 }
10174
10175 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)
10176 {
10177         tridecal_t *decal;
10178         tridecal_t *decals;
10179         int i;
10180
10181         // expand or initialize the system
10182         if (decalsystem->maxdecals <= decalsystem->numdecals)
10183         {
10184                 decalsystem_t old = *decalsystem;
10185                 qboolean useshortelements;
10186                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10187                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10188                 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)));
10189                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10190                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10191                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10192                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10193                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10194                 if (decalsystem->numdecals)
10195                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10196                 if (old.decals)
10197                         Mem_Free(old.decals);
10198                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10199                         decalsystem->element3i[i] = i;
10200                 if (useshortelements)
10201                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10202                                 decalsystem->element3s[i] = i;
10203         }
10204
10205         // grab a decal and search for another free slot for the next one
10206         decals = decalsystem->decals;
10207         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10208         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10209                 ;
10210         decalsystem->freedecal = i;
10211         if (decalsystem->numdecals <= i)
10212                 decalsystem->numdecals = i + 1;
10213
10214         // initialize the decal
10215         decal->lived = 0;
10216         decal->triangleindex = triangleindex;
10217         decal->surfaceindex = surfaceindex;
10218         decal->decalsequence = decalsequence;
10219         decal->color4f[0][0] = c0[0];
10220         decal->color4f[0][1] = c0[1];
10221         decal->color4f[0][2] = c0[2];
10222         decal->color4f[0][3] = 1;
10223         decal->color4f[1][0] = c1[0];
10224         decal->color4f[1][1] = c1[1];
10225         decal->color4f[1][2] = c1[2];
10226         decal->color4f[1][3] = 1;
10227         decal->color4f[2][0] = c2[0];
10228         decal->color4f[2][1] = c2[1];
10229         decal->color4f[2][2] = c2[2];
10230         decal->color4f[2][3] = 1;
10231         decal->vertex3f[0][0] = v0[0];
10232         decal->vertex3f[0][1] = v0[1];
10233         decal->vertex3f[0][2] = v0[2];
10234         decal->vertex3f[1][0] = v1[0];
10235         decal->vertex3f[1][1] = v1[1];
10236         decal->vertex3f[1][2] = v1[2];
10237         decal->vertex3f[2][0] = v2[0];
10238         decal->vertex3f[2][1] = v2[1];
10239         decal->vertex3f[2][2] = v2[2];
10240         decal->texcoord2f[0][0] = t0[0];
10241         decal->texcoord2f[0][1] = t0[1];
10242         decal->texcoord2f[1][0] = t1[0];
10243         decal->texcoord2f[1][1] = t1[1];
10244         decal->texcoord2f[2][0] = t2[0];
10245         decal->texcoord2f[2][1] = t2[1];
10246 }
10247
10248 extern cvar_t cl_decals_bias;
10249 extern cvar_t cl_decals_models;
10250 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10251 // baseparms, parms, temps
10252 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)
10253 {
10254         int cornerindex;
10255         int index;
10256         float v[9][3];
10257         const float *vertex3f;
10258         const float *normal3f;
10259         int numpoints;
10260         float points[2][9][3];
10261         float temp[3];
10262         float tc[9][2];
10263         float f;
10264         float c[9][4];
10265         const int *e;
10266
10267         e = rsurface.modelelement3i + 3*triangleindex;
10268
10269         vertex3f = rsurface.modelvertex3f;
10270         normal3f = rsurface.modelnormal3f;
10271
10272         for (cornerindex = 0;cornerindex < 3;cornerindex++)
10273         {
10274                 index = 3*e[cornerindex];
10275                 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10276         }
10277         // cull backfaces
10278         //TriangleNormal(v[0], v[1], v[2], normal);
10279         //if (DotProduct(normal, localnormal) < 0.0f)
10280         //      continue;
10281         // clip by each of the box planes formed from the projection matrix
10282         // if anything survives, we emit the decal
10283         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]);
10284         if (numpoints < 3)
10285                 return;
10286         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]);
10287         if (numpoints < 3)
10288                 return;
10289         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]);
10290         if (numpoints < 3)
10291                 return;
10292         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]);
10293         if (numpoints < 3)
10294                 return;
10295         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]);
10296         if (numpoints < 3)
10297                 return;
10298         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]);
10299         if (numpoints < 3)
10300                 return;
10301         // some part of the triangle survived, so we have to accept it...
10302         if (dynamic)
10303         {
10304                 // dynamic always uses the original triangle
10305                 numpoints = 3;
10306                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10307                 {
10308                         index = 3*e[cornerindex];
10309                         VectorCopy(vertex3f + index, v[cornerindex]);
10310                 }
10311         }
10312         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10313         {
10314                 // convert vertex positions to texcoords
10315                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10316                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10317                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10318                 // calculate distance fade from the projection origin
10319                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10320                 f = bound(0.0f, f, 1.0f);
10321                 c[cornerindex][0] = r * f;
10322                 c[cornerindex][1] = g * f;
10323                 c[cornerindex][2] = b * f;
10324                 c[cornerindex][3] = 1.0f;
10325                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10326         }
10327         if (dynamic)
10328                 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);
10329         else
10330                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10331                         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);
10332 }
10333 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)
10334 {
10335         matrix4x4_t projection;
10336         decalsystem_t *decalsystem;
10337         qboolean dynamic;
10338         dp_model_t *model;
10339         const msurface_t *surface;
10340         const msurface_t *surfaces;
10341         const int *surfacelist;
10342         const texture_t *texture;
10343         int numtriangles;
10344         int numsurfacelist;
10345         int surfacelistindex;
10346         int surfaceindex;
10347         int triangleindex;
10348         float localorigin[3];
10349         float localnormal[3];
10350         float localmins[3];
10351         float localmaxs[3];
10352         float localsize;
10353         //float normal[3];
10354         float planes[6][4];
10355         float angles[3];
10356         bih_t *bih;
10357         int bih_triangles_count;
10358         int bih_triangles[256];
10359         int bih_surfaces[256];
10360
10361         decalsystem = &ent->decalsystem;
10362         model = ent->model;
10363         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10364         {
10365                 R_DecalSystem_Reset(&ent->decalsystem);
10366                 return;
10367         }
10368
10369         if (!model->brush.data_leafs && !cl_decals_models.integer)
10370         {
10371                 if (decalsystem->model)
10372                         R_DecalSystem_Reset(decalsystem);
10373                 return;
10374         }
10375
10376         if (decalsystem->model != model)
10377                 R_DecalSystem_Reset(decalsystem);
10378         decalsystem->model = model;
10379
10380         RSurf_ActiveModelEntity(ent, true, false, false);
10381
10382         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10383         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10384         VectorNormalize(localnormal);
10385         localsize = worldsize*rsurface.inversematrixscale;
10386         localmins[0] = localorigin[0] - localsize;
10387         localmins[1] = localorigin[1] - localsize;
10388         localmins[2] = localorigin[2] - localsize;
10389         localmaxs[0] = localorigin[0] + localsize;
10390         localmaxs[1] = localorigin[1] + localsize;
10391         localmaxs[2] = localorigin[2] + localsize;
10392
10393         //VectorCopy(localnormal, planes[4]);
10394         //VectorVectors(planes[4], planes[2], planes[0]);
10395         AnglesFromVectors(angles, localnormal, NULL, false);
10396         AngleVectors(angles, planes[0], planes[2], planes[4]);
10397         VectorNegate(planes[0], planes[1]);
10398         VectorNegate(planes[2], planes[3]);
10399         VectorNegate(planes[4], planes[5]);
10400         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10401         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10402         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10403         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10404         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10405         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10406
10407 #if 1
10408 // works
10409 {
10410         matrix4x4_t forwardprojection;
10411         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10412         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10413 }
10414 #else
10415 // broken
10416 {
10417         float projectionvector[4][3];
10418         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10419         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10420         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10421         projectionvector[0][0] = planes[0][0] * ilocalsize;
10422         projectionvector[0][1] = planes[1][0] * ilocalsize;
10423         projectionvector[0][2] = planes[2][0] * ilocalsize;
10424         projectionvector[1][0] = planes[0][1] * ilocalsize;
10425         projectionvector[1][1] = planes[1][1] * ilocalsize;
10426         projectionvector[1][2] = planes[2][1] * ilocalsize;
10427         projectionvector[2][0] = planes[0][2] * ilocalsize;
10428         projectionvector[2][1] = planes[1][2] * ilocalsize;
10429         projectionvector[2][2] = planes[2][2] * ilocalsize;
10430         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10431         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10432         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10433         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10434 }
10435 #endif
10436
10437         dynamic = model->surfmesh.isanimated;
10438         numsurfacelist = model->nummodelsurfaces;
10439         surfacelist = model->sortedmodelsurfaces;
10440         surfaces = model->data_surfaces;
10441
10442         bih = NULL;
10443         bih_triangles_count = -1;
10444         if(!dynamic)
10445         {
10446                 if(model->render_bih.numleafs)
10447                         bih = &model->render_bih;
10448                 else if(model->collision_bih.numleafs)
10449                         bih = &model->collision_bih;
10450         }
10451         if(bih)
10452                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10453         if(bih_triangles_count == 0)
10454                 return;
10455         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10456                 return;
10457         if(bih_triangles_count > 0)
10458         {
10459                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10460                 {
10461                         surfaceindex = bih_surfaces[triangleindex];
10462                         surface = surfaces + surfaceindex;
10463                         texture = surface->texture;
10464                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10465                                 continue;
10466                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10467                                 continue;
10468                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10469                 }
10470         }
10471         else
10472         {
10473                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10474                 {
10475                         surfaceindex = surfacelist[surfacelistindex];
10476                         surface = surfaces + surfaceindex;
10477                         // check cull box first because it rejects more than any other check
10478                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10479                                 continue;
10480                         // skip transparent surfaces
10481                         texture = surface->texture;
10482                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10483                                 continue;
10484                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10485                                 continue;
10486                         numtriangles = surface->num_triangles;
10487                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10488                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10489                 }
10490         }
10491 }
10492
10493 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10494 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)
10495 {
10496         int renderentityindex;
10497         float worldmins[3];
10498         float worldmaxs[3];
10499         entity_render_t *ent;
10500
10501         if (!cl_decals_newsystem.integer)
10502                 return;
10503
10504         worldmins[0] = worldorigin[0] - worldsize;
10505         worldmins[1] = worldorigin[1] - worldsize;
10506         worldmins[2] = worldorigin[2] - worldsize;
10507         worldmaxs[0] = worldorigin[0] + worldsize;
10508         worldmaxs[1] = worldorigin[1] + worldsize;
10509         worldmaxs[2] = worldorigin[2] + worldsize;
10510
10511         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10512
10513         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10514         {
10515                 ent = r_refdef.scene.entities[renderentityindex];
10516                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10517                         continue;
10518
10519                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10520         }
10521 }
10522
10523 typedef struct r_decalsystem_splatqueue_s
10524 {
10525         vec3_t worldorigin;
10526         vec3_t worldnormal;
10527         float color[4];
10528         float tcrange[4];
10529         float worldsize;
10530         int decalsequence;
10531 }
10532 r_decalsystem_splatqueue_t;
10533
10534 int r_decalsystem_numqueued = 0;
10535 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10536
10537 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)
10538 {
10539         r_decalsystem_splatqueue_t *queue;
10540
10541         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10542                 return;
10543
10544         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10545         VectorCopy(worldorigin, queue->worldorigin);
10546         VectorCopy(worldnormal, queue->worldnormal);
10547         Vector4Set(queue->color, r, g, b, a);
10548         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10549         queue->worldsize = worldsize;
10550         queue->decalsequence = cl.decalsequence++;
10551 }
10552
10553 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10554 {
10555         int i;
10556         r_decalsystem_splatqueue_t *queue;
10557
10558         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10559                 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);
10560         r_decalsystem_numqueued = 0;
10561 }
10562
10563 extern cvar_t cl_decals_max;
10564 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10565 {
10566         int i;
10567         decalsystem_t *decalsystem = &ent->decalsystem;
10568         int numdecals;
10569         int killsequence;
10570         tridecal_t *decal;
10571         float frametime;
10572         float lifetime;
10573
10574         if (!decalsystem->numdecals)
10575                 return;
10576
10577         if (r_showsurfaces.integer)
10578                 return;
10579
10580         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10581         {
10582                 R_DecalSystem_Reset(decalsystem);
10583                 return;
10584         }
10585
10586         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10587         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10588
10589         if (decalsystem->lastupdatetime)
10590                 frametime = (cl.time - decalsystem->lastupdatetime);
10591         else
10592                 frametime = 0;
10593         decalsystem->lastupdatetime = cl.time;
10594         decal = decalsystem->decals;
10595         numdecals = decalsystem->numdecals;
10596
10597         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10598         {
10599                 if (decal->color4f[0][3])
10600                 {
10601                         decal->lived += frametime;
10602                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10603                         {
10604                                 memset(decal, 0, sizeof(*decal));
10605                                 if (decalsystem->freedecal > i)
10606                                         decalsystem->freedecal = i;
10607                         }
10608                 }
10609         }
10610         decal = decalsystem->decals;
10611         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10612                 numdecals--;
10613
10614         // collapse the array by shuffling the tail decals into the gaps
10615         for (;;)
10616         {
10617                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10618                         decalsystem->freedecal++;
10619                 if (decalsystem->freedecal == numdecals)
10620                         break;
10621                 decal[decalsystem->freedecal] = decal[--numdecals];
10622         }
10623
10624         decalsystem->numdecals = numdecals;
10625
10626         if (numdecals <= 0)
10627         {
10628                 // if there are no decals left, reset decalsystem
10629                 R_DecalSystem_Reset(decalsystem);
10630         }
10631 }
10632
10633 extern skinframe_t *decalskinframe;
10634 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10635 {
10636         int i;
10637         decalsystem_t *decalsystem = &ent->decalsystem;
10638         int numdecals;
10639         tridecal_t *decal;
10640         float faderate;
10641         float alpha;
10642         float *v3f;
10643         float *c4f;
10644         float *t2f;
10645         const int *e;
10646         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10647         int numtris = 0;
10648
10649         numdecals = decalsystem->numdecals;
10650         if (!numdecals)
10651                 return;
10652
10653         if (r_showsurfaces.integer)
10654                 return;
10655
10656         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10657         {
10658                 R_DecalSystem_Reset(decalsystem);
10659                 return;
10660         }
10661
10662         // if the model is static it doesn't matter what value we give for
10663         // wantnormals and wanttangents, so this logic uses only rules applicable
10664         // to a model, knowing that they are meaningless otherwise
10665         if (ent == r_refdef.scene.worldentity)
10666                 RSurf_ActiveWorldEntity();
10667         else
10668                 RSurf_ActiveModelEntity(ent, false, false, false);
10669
10670         decalsystem->lastupdatetime = cl.time;
10671         decal = decalsystem->decals;
10672
10673         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10674
10675         // update vertex positions for animated models
10676         v3f = decalsystem->vertex3f;
10677         c4f = decalsystem->color4f;
10678         t2f = decalsystem->texcoord2f;
10679         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10680         {
10681                 if (!decal->color4f[0][3])
10682                         continue;
10683
10684                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10685                         continue;
10686
10687                 // update color values for fading decals
10688                 if (decal->lived >= cl_decals_time.value)
10689                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10690                 else
10691                         alpha = 1.0f;
10692
10693                 c4f[ 0] = decal->color4f[0][0] * alpha;
10694                 c4f[ 1] = decal->color4f[0][1] * alpha;
10695                 c4f[ 2] = decal->color4f[0][2] * alpha;
10696                 c4f[ 3] = 1;
10697                 c4f[ 4] = decal->color4f[1][0] * alpha;
10698                 c4f[ 5] = decal->color4f[1][1] * alpha;
10699                 c4f[ 6] = decal->color4f[1][2] * alpha;
10700                 c4f[ 7] = 1;
10701                 c4f[ 8] = decal->color4f[2][0] * alpha;
10702                 c4f[ 9] = decal->color4f[2][1] * alpha;
10703                 c4f[10] = decal->color4f[2][2] * alpha;
10704                 c4f[11] = 1;
10705
10706                 t2f[0] = decal->texcoord2f[0][0];
10707                 t2f[1] = decal->texcoord2f[0][1];
10708                 t2f[2] = decal->texcoord2f[1][0];
10709                 t2f[3] = decal->texcoord2f[1][1];
10710                 t2f[4] = decal->texcoord2f[2][0];
10711                 t2f[5] = decal->texcoord2f[2][1];
10712
10713                 // update vertex positions for animated models
10714                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10715                 {
10716                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10717                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10718                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10719                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10720                 }
10721                 else
10722                 {
10723                         VectorCopy(decal->vertex3f[0], v3f);
10724                         VectorCopy(decal->vertex3f[1], v3f + 3);
10725                         VectorCopy(decal->vertex3f[2], v3f + 6);
10726                 }
10727
10728                 if (r_refdef.fogenabled)
10729                 {
10730                         alpha = RSurf_FogVertex(v3f);
10731                         VectorScale(c4f, alpha, c4f);
10732                         alpha = RSurf_FogVertex(v3f + 3);
10733                         VectorScale(c4f + 4, alpha, c4f + 4);
10734                         alpha = RSurf_FogVertex(v3f + 6);
10735                         VectorScale(c4f + 8, alpha, c4f + 8);
10736                 }
10737
10738                 v3f += 9;
10739                 c4f += 12;
10740                 t2f += 6;
10741                 numtris++;
10742         }
10743
10744         if (numtris > 0)
10745         {
10746                 r_refdef.stats.drawndecals += numtris;
10747
10748                 // now render the decals all at once
10749                 // (this assumes they all use one particle font texture!)
10750                 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);
10751 //              R_Mesh_ResetTextureState();
10752                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10753                 GL_DepthMask(false);
10754                 GL_DepthRange(0, 1);
10755                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10756                 GL_DepthTest(true);
10757                 GL_CullFace(GL_NONE);
10758                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10759                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10760                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10761         }
10762 }
10763
10764 static void R_DrawModelDecals(void)
10765 {
10766         int i, numdecals;
10767
10768         // fade faster when there are too many decals
10769         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10770         for (i = 0;i < r_refdef.scene.numentities;i++)
10771                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10772
10773         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10774         for (i = 0;i < r_refdef.scene.numentities;i++)
10775                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10776                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10777
10778         R_DecalSystem_ApplySplatEntitiesQueue();
10779
10780         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10781         for (i = 0;i < r_refdef.scene.numentities;i++)
10782                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10783
10784         r_refdef.stats.totaldecals += numdecals;
10785
10786         if (r_showsurfaces.integer)
10787                 return;
10788
10789         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10790
10791         for (i = 0;i < r_refdef.scene.numentities;i++)
10792         {
10793                 if (!r_refdef.viewcache.entityvisible[i])
10794                         continue;
10795                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10796                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10797         }
10798 }
10799
10800 extern cvar_t mod_collision_bih;
10801 void R_DrawDebugModel(void)
10802 {
10803         entity_render_t *ent = rsurface.entity;
10804         int i, j, k, l, flagsmask;
10805         const msurface_t *surface;
10806         dp_model_t *model = ent->model;
10807         vec3_t v;
10808
10809         switch(vid.renderpath)
10810         {
10811         case RENDERPATH_GL11:
10812         case RENDERPATH_GL13:
10813         case RENDERPATH_GL20:
10814                 break;
10815         case RENDERPATH_D3D9:
10816                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10817                 return;
10818         case RENDERPATH_D3D10:
10819                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10820                 return;
10821         case RENDERPATH_D3D11:
10822                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10823                 return;
10824         case RENDERPATH_SOFT:
10825                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10826                 return;
10827         case RENDERPATH_GLES2:
10828                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10829                 return;
10830         }
10831
10832         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10833
10834 //      R_Mesh_ResetTextureState();
10835         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10836         GL_DepthRange(0, 1);
10837         GL_DepthTest(!r_showdisabledepthtest.integer);
10838         GL_DepthMask(false);
10839         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10840
10841         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10842         {
10843                 int triangleindex;
10844                 int bihleafindex;
10845                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10846                 const q3mbrush_t *brush;
10847                 const bih_t *bih = &model->collision_bih;
10848                 const bih_leaf_t *bihleaf;
10849                 float vertex3f[3][3];
10850                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10851                 cullbox = false;
10852                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10853                 {
10854                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10855                                 continue;
10856                         switch (bihleaf->type)
10857                         {
10858                         case BIH_BRUSH:
10859                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10860                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10861                                 {
10862                                         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);
10863                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10864                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10865                                 }
10866                                 break;
10867                         case BIH_COLLISIONTRIANGLE:
10868                                 triangleindex = bihleaf->itemindex;
10869                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10870                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10871                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10872                                 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);
10873                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10874                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10875                                 break;
10876                         case BIH_RENDERTRIANGLE:
10877                                 triangleindex = bihleaf->itemindex;
10878                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10879                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10880                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10881                                 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);
10882                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10883                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10884                                 break;
10885                         }
10886                 }
10887         }
10888
10889         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10890
10891         if (r_showtris.integer || (r_shownormals.value != 0))
10892         {
10893                 if (r_showdisabledepthtest.integer)
10894                 {
10895                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10896                         GL_DepthMask(false);
10897                 }
10898                 else
10899                 {
10900                         GL_BlendFunc(GL_ONE, GL_ZERO);
10901                         GL_DepthMask(true);
10902                 }
10903                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10904                 {
10905                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10906                                 continue;
10907                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10908                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10909                         {
10910                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10911                                 if (r_showtris.value > 0)
10912                                 {
10913                                         if (!rsurface.texture->currentlayers->depthmask)
10914                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10915                                         else if (ent == r_refdef.scene.worldentity)
10916                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10917                                         else
10918                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10919                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10920                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10921                                         RSurf_DrawBatch();
10922                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10923                                         CHECKGLERROR
10924                                 }
10925                                 if (r_shownormals.value < 0)
10926                                 {
10927                                         qglBegin(GL_LINES);
10928                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10929                                         {
10930                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10931                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10932                                                 qglVertex3f(v[0], v[1], v[2]);
10933                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10934                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10935                                                 qglVertex3f(v[0], v[1], v[2]);
10936                                         }
10937                                         qglEnd();
10938                                         CHECKGLERROR
10939                                 }
10940                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10941                                 {
10942                                         qglBegin(GL_LINES);
10943                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10944                                         {
10945                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10946                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10947                                                 qglVertex3f(v[0], v[1], v[2]);
10948                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10949                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10950                                                 qglVertex3f(v[0], v[1], v[2]);
10951                                         }
10952                                         qglEnd();
10953                                         CHECKGLERROR
10954                                         qglBegin(GL_LINES);
10955                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10956                                         {
10957                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10958                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10959                                                 qglVertex3f(v[0], v[1], v[2]);
10960                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10961                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10962                                                 qglVertex3f(v[0], v[1], v[2]);
10963                                         }
10964                                         qglEnd();
10965                                         CHECKGLERROR
10966                                         qglBegin(GL_LINES);
10967                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10968                                         {
10969                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10970                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10971                                                 qglVertex3f(v[0], v[1], v[2]);
10972                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10973                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10974                                                 qglVertex3f(v[0], v[1], v[2]);
10975                                         }
10976                                         qglEnd();
10977                                         CHECKGLERROR
10978                                 }
10979                         }
10980                 }
10981                 rsurface.texture = NULL;
10982         }
10983 }
10984
10985 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10986 int r_maxsurfacelist = 0;
10987 const msurface_t **r_surfacelist = NULL;
10988 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10989 {
10990         int i, j, endj, flagsmask;
10991         dp_model_t *model = r_refdef.scene.worldmodel;
10992         msurface_t *surfaces;
10993         unsigned char *update;
10994         int numsurfacelist = 0;
10995         if (model == NULL)
10996                 return;
10997
10998         if (r_maxsurfacelist < model->num_surfaces)
10999         {
11000                 r_maxsurfacelist = model->num_surfaces;
11001                 if (r_surfacelist)
11002                         Mem_Free((msurface_t**)r_surfacelist);
11003                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11004         }
11005
11006         RSurf_ActiveWorldEntity();
11007
11008         surfaces = model->data_surfaces;
11009         update = model->brushq1.lightmapupdateflags;
11010
11011         // update light styles on this submodel
11012         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11013         {
11014                 model_brush_lightstyleinfo_t *style;
11015                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11016                 {
11017                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11018                         {
11019                                 int *list = style->surfacelist;
11020                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11021                                 for (j = 0;j < style->numsurfaces;j++)
11022                                         update[list[j]] = true;
11023                         }
11024                 }
11025         }
11026
11027         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11028
11029         if (debug)
11030         {
11031                 R_DrawDebugModel();
11032                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11033                 return;
11034         }
11035
11036         rsurface.lightmaptexture = NULL;
11037         rsurface.deluxemaptexture = NULL;
11038         rsurface.uselightmaptexture = false;
11039         rsurface.texture = NULL;
11040         rsurface.rtlight = NULL;
11041         numsurfacelist = 0;
11042         // add visible surfaces to draw list
11043         for (i = 0;i < model->nummodelsurfaces;i++)
11044         {
11045                 j = model->sortedmodelsurfaces[i];
11046                 if (r_refdef.viewcache.world_surfacevisible[j])
11047                         r_surfacelist[numsurfacelist++] = surfaces + j;
11048         }
11049         // update lightmaps if needed
11050         if (model->brushq1.firstrender)
11051         {
11052                 model->brushq1.firstrender = false;
11053                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11054                         if (update[j])
11055                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11056         }
11057         else if (update)
11058         {
11059                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11060                         if (r_refdef.viewcache.world_surfacevisible[j])
11061                                 if (update[j])
11062                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11063         }
11064         // don't do anything if there were no surfaces
11065         if (!numsurfacelist)
11066         {
11067                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11068                 return;
11069         }
11070         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11071
11072         // add to stats if desired
11073         if (r_speeds.integer && !skysurfaces && !depthonly)
11074         {
11075                 r_refdef.stats.world_surfaces += numsurfacelist;
11076                 for (j = 0;j < numsurfacelist;j++)
11077                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11078         }
11079
11080         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11081 }
11082
11083 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11084 {
11085         int i, j, endj, flagsmask;
11086         dp_model_t *model = ent->model;
11087         msurface_t *surfaces;
11088         unsigned char *update;
11089         int numsurfacelist = 0;
11090         if (model == NULL)
11091                 return;
11092
11093         if (r_maxsurfacelist < model->num_surfaces)
11094         {
11095                 r_maxsurfacelist = model->num_surfaces;
11096                 if (r_surfacelist)
11097                         Mem_Free((msurface_t **)r_surfacelist);
11098                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11099         }
11100
11101         // if the model is static it doesn't matter what value we give for
11102         // wantnormals and wanttangents, so this logic uses only rules applicable
11103         // to a model, knowing that they are meaningless otherwise
11104         if (ent == r_refdef.scene.worldentity)
11105                 RSurf_ActiveWorldEntity();
11106         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11107                 RSurf_ActiveModelEntity(ent, false, false, false);
11108         else if (prepass)
11109                 RSurf_ActiveModelEntity(ent, true, true, true);
11110         else if (depthonly)
11111         {
11112                 switch (vid.renderpath)
11113                 {
11114                 case RENDERPATH_GL20:
11115                 case RENDERPATH_D3D9:
11116                 case RENDERPATH_D3D10:
11117                 case RENDERPATH_D3D11:
11118                 case RENDERPATH_SOFT:
11119                 case RENDERPATH_GLES2:
11120                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11121                         break;
11122                 case RENDERPATH_GL13:
11123                 case RENDERPATH_GL11:
11124                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11125                         break;
11126                 }
11127         }
11128         else
11129         {
11130                 switch (vid.renderpath)
11131                 {
11132                 case RENDERPATH_GL20:
11133                 case RENDERPATH_D3D9:
11134                 case RENDERPATH_D3D10:
11135                 case RENDERPATH_D3D11:
11136                 case RENDERPATH_SOFT:
11137                 case RENDERPATH_GLES2:
11138                         RSurf_ActiveModelEntity(ent, true, true, false);
11139                         break;
11140                 case RENDERPATH_GL13:
11141                 case RENDERPATH_GL11:
11142                         RSurf_ActiveModelEntity(ent, true, false, false);
11143                         break;
11144                 }
11145         }
11146
11147         surfaces = model->data_surfaces;
11148         update = model->brushq1.lightmapupdateflags;
11149
11150         // update light styles
11151         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11152         {
11153                 model_brush_lightstyleinfo_t *style;
11154                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11155                 {
11156                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11157                         {
11158                                 int *list = style->surfacelist;
11159                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11160                                 for (j = 0;j < style->numsurfaces;j++)
11161                                         update[list[j]] = true;
11162                         }
11163                 }
11164         }
11165
11166         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11167
11168         if (debug)
11169         {
11170                 R_DrawDebugModel();
11171                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11172                 return;
11173         }
11174
11175         rsurface.lightmaptexture = NULL;
11176         rsurface.deluxemaptexture = NULL;
11177         rsurface.uselightmaptexture = false;
11178         rsurface.texture = NULL;
11179         rsurface.rtlight = NULL;
11180         numsurfacelist = 0;
11181         // add visible surfaces to draw list
11182         for (i = 0;i < model->nummodelsurfaces;i++)
11183                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11184         // don't do anything if there were no surfaces
11185         if (!numsurfacelist)
11186         {
11187                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11188                 return;
11189         }
11190         // update lightmaps if needed
11191         if (update)
11192         {
11193                 int updated = 0;
11194                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11195                 {
11196                         if (update[j])
11197                         {
11198                                 updated++;
11199                                 R_BuildLightMap(ent, surfaces + j);
11200                         }
11201                 }
11202         }
11203         if (update)
11204                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11205                         if (update[j])
11206                                 R_BuildLightMap(ent, surfaces + j);
11207         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11208
11209         // add to stats if desired
11210         if (r_speeds.integer && !skysurfaces && !depthonly)
11211         {
11212                 r_refdef.stats.entities_surfaces += numsurfacelist;
11213                 for (j = 0;j < numsurfacelist;j++)
11214                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11215         }
11216
11217         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11218 }
11219
11220 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11221 {
11222         static texture_t texture;
11223         static msurface_t surface;
11224         const msurface_t *surfacelist = &surface;
11225
11226         // fake enough texture and surface state to render this geometry
11227
11228         texture.update_lastrenderframe = -1; // regenerate this texture
11229         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11230         texture.currentskinframe = skinframe;
11231         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11232         texture.offsetmapping = OFFSETMAPPING_OFF;
11233         texture.offsetscale = 1;
11234         texture.specularscalemod = 1;
11235         texture.specularpowermod = 1;
11236
11237         surface.texture = &texture;
11238         surface.num_triangles = numtriangles;
11239         surface.num_firsttriangle = firsttriangle;
11240         surface.num_vertices = numvertices;
11241         surface.num_firstvertex = firstvertex;
11242
11243         // now render it
11244         rsurface.texture = R_GetCurrentTexture(surface.texture);
11245         rsurface.lightmaptexture = NULL;
11246         rsurface.deluxemaptexture = NULL;
11247         rsurface.uselightmaptexture = false;
11248         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11249 }
11250
11251 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)
11252 {
11253         static msurface_t surface;
11254         const msurface_t *surfacelist = &surface;
11255
11256         // fake enough texture and surface state to render this geometry
11257         surface.texture = texture;
11258         surface.num_triangles = numtriangles;
11259         surface.num_firsttriangle = firsttriangle;
11260         surface.num_vertices = numvertices;
11261         surface.num_firstvertex = firstvertex;
11262
11263         // now render it
11264         rsurface.texture = R_GetCurrentTexture(surface.texture);
11265         rsurface.lightmaptexture = NULL;
11266         rsurface.deluxemaptexture = NULL;
11267         rsurface.uselightmaptexture = false;
11268         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11269 }