2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
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"};
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"};
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"};
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))
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"};
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)"};
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"};
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"};
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"};
143 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
157 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
181 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
182 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
183 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
184 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
185 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
186 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
188 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
190 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
192 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
194 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
195 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
196 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
197 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
198 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
199 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
200 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
201 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
202 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
204 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
205 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
207 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
209 extern cvar_t v_glslgamma;
211 extern qboolean v_flipped_state;
213 static struct r_bloomstate_s
218 int bloomwidth, bloomheight;
220 int screentexturewidth, screentextureheight;
221 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
223 int bloomtexturewidth, bloomtextureheight;
224 rtexture_t *texture_bloom;
226 // arrays for rendering the screen passes
227 float screentexcoord2f[8];
228 float bloomtexcoord2f[8];
229 float offsettexcoord2f[8];
231 r_viewport_t viewport;
235 r_waterstate_t r_waterstate;
237 /// shadow volume bsp struct with automatically growing nodes buffer
240 rtexture_t *r_texture_blanknormalmap;
241 rtexture_t *r_texture_white;
242 rtexture_t *r_texture_grey128;
243 rtexture_t *r_texture_black;
244 rtexture_t *r_texture_notexture;
245 rtexture_t *r_texture_whitecube;
246 rtexture_t *r_texture_normalizationcube;
247 rtexture_t *r_texture_fogattenuation;
248 rtexture_t *r_texture_fogheighttexture;
249 rtexture_t *r_texture_gammaramps;
250 unsigned int r_texture_gammaramps_serial;
251 //rtexture_t *r_texture_fogintensity;
252 rtexture_t *r_texture_reflectcube;
254 // TODO: hash lookups?
255 typedef struct cubemapinfo_s
262 int r_texture_numcubemaps;
263 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
265 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
266 unsigned int r_numqueries;
267 unsigned int r_maxqueries;
269 typedef struct r_qwskincache_s
271 char name[MAX_QPATH];
272 skinframe_t *skinframe;
276 static r_qwskincache_t *r_qwskincache;
277 static int r_qwskincache_size;
279 /// vertex coordinates for a quad that covers the screen exactly
280 extern const float r_screenvertex3f[12];
281 extern const float r_d3dscreenvertex3f[12];
282 const float r_screenvertex3f[12] =
289 const float r_d3dscreenvertex3f[12] =
297 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
300 for (i = 0;i < verts;i++)
311 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
314 for (i = 0;i < verts;i++)
324 // FIXME: move this to client?
327 if (gamemode == GAME_NEHAHRA)
329 Cvar_Set("gl_fogenable", "0");
330 Cvar_Set("gl_fogdensity", "0.2");
331 Cvar_Set("gl_fogred", "0.3");
332 Cvar_Set("gl_foggreen", "0.3");
333 Cvar_Set("gl_fogblue", "0.3");
335 r_refdef.fog_density = 0;
336 r_refdef.fog_red = 0;
337 r_refdef.fog_green = 0;
338 r_refdef.fog_blue = 0;
339 r_refdef.fog_alpha = 1;
340 r_refdef.fog_start = 0;
341 r_refdef.fog_end = 16384;
342 r_refdef.fog_height = 1<<30;
343 r_refdef.fog_fadedepth = 128;
344 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
347 static void R_BuildBlankTextures(void)
349 unsigned char data[4];
350 data[2] = 128; // normal X
351 data[1] = 128; // normal Y
352 data[0] = 255; // normal Z
353 data[3] = 128; // height
354 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
369 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
372 static void R_BuildNoTexture(void)
375 unsigned char pix[16][16][4];
376 // this makes a light grey/dark grey checkerboard texture
377 for (y = 0;y < 16;y++)
379 for (x = 0;x < 16;x++)
381 if ((y < 8) ^ (x < 8))
397 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
400 static void R_BuildWhiteCube(void)
402 unsigned char data[6*1*1*4];
403 memset(data, 255, sizeof(data));
404 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
407 static void R_BuildNormalizationCube(void)
411 vec_t s, t, intensity;
414 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
415 for (side = 0;side < 6;side++)
417 for (y = 0;y < NORMSIZE;y++)
419 for (x = 0;x < NORMSIZE;x++)
421 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
422 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
457 intensity = 127.0f / sqrt(DotProduct(v, v));
458 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
459 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
460 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
461 data[((side*64+y)*64+x)*4+3] = 255;
465 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
469 static void R_BuildFogTexture(void)
473 unsigned char data1[FOGWIDTH][4];
474 //unsigned char data2[FOGWIDTH][4];
477 r_refdef.fogmasktable_start = r_refdef.fog_start;
478 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
479 r_refdef.fogmasktable_range = r_refdef.fogrange;
480 r_refdef.fogmasktable_density = r_refdef.fog_density;
482 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
483 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
485 d = (x * r - r_refdef.fogmasktable_start);
486 if(developer_extra.integer)
487 Con_DPrintf("%f ", d);
489 if (r_fog_exp2.integer)
490 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
492 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
493 if(developer_extra.integer)
494 Con_DPrintf(" : %f ", alpha);
495 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
496 if(developer_extra.integer)
497 Con_DPrintf(" = %f\n", alpha);
498 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
501 for (x = 0;x < FOGWIDTH;x++)
503 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
508 //data2[x][0] = 255 - b;
509 //data2[x][1] = 255 - b;
510 //data2[x][2] = 255 - b;
513 if (r_texture_fogattenuation)
515 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
516 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
520 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
521 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
525 static void R_BuildFogHeightTexture(void)
527 unsigned char *inpixels;
535 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
536 if (r_refdef.fogheighttexturename[0])
537 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
540 r_refdef.fog_height_tablesize = 0;
541 if (r_texture_fogheighttexture)
542 R_FreeTexture(r_texture_fogheighttexture);
543 r_texture_fogheighttexture = NULL;
544 if (r_refdef.fog_height_table2d)
545 Mem_Free(r_refdef.fog_height_table2d);
546 r_refdef.fog_height_table2d = NULL;
547 if (r_refdef.fog_height_table1d)
548 Mem_Free(r_refdef.fog_height_table1d);
549 r_refdef.fog_height_table1d = NULL;
553 r_refdef.fog_height_tablesize = size;
554 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
555 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
556 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
558 // LordHavoc: now the magic - what is that table2d for? it is a cooked
559 // average fog color table accounting for every fog layer between a point
560 // and the camera. (Note: attenuation is handled separately!)
561 for (y = 0;y < size;y++)
563 for (x = 0;x < size;x++)
569 for (j = x;j <= y;j++)
571 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
577 for (j = x;j >= y;j--)
579 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
584 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
585 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
586 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
587 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
590 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
593 //=======================================================================================================================================================
595 static const char *builtinshaderstring =
596 #include "shader_glsl.h"
599 const char *builtinhlslshaderstring =
600 #include "shader_hlsl.h"
603 char *glslshaderstring = NULL;
604 char *hlslshaderstring = NULL;
606 //=======================================================================================================================================================
608 typedef struct shaderpermutationinfo_s
613 shaderpermutationinfo_t;
615 typedef struct shadermodeinfo_s
617 const char *vertexfilename;
618 const char *geometryfilename;
619 const char *fragmentfilename;
625 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
626 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
628 {"#define USEDIFFUSE\n", " diffuse"},
629 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
630 {"#define USEVIEWTINT\n", " viewtint"},
631 {"#define USECOLORMAPPING\n", " colormapping"},
632 {"#define USESATURATION\n", " saturation"},
633 {"#define USEFOGINSIDE\n", " foginside"},
634 {"#define USEFOGOUTSIDE\n", " fogoutside"},
635 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
636 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
637 {"#define USEGAMMARAMPS\n", " gammaramps"},
638 {"#define USECUBEFILTER\n", " cubefilter"},
639 {"#define USEGLOW\n", " glow"},
640 {"#define USEBLOOM\n", " bloom"},
641 {"#define USESPECULAR\n", " specular"},
642 {"#define USEPOSTPROCESSING\n", " postprocessing"},
643 {"#define USEREFLECTION\n", " reflection"},
644 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
645 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
646 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
647 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
648 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
649 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
650 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
651 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
652 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
653 {"#define USEALPHAKILL\n", " alphakill"},
654 {"#define USEREFLECTCUBE\n", " reflectcube"},
655 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
656 {"#define USEBOUNCEGRID\n", " bouncegrid"},
659 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
660 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
662 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
663 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
664 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
665 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
666 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
667 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
668 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
669 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
670 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
671 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
672 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
673 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
674 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
675 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
676 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
677 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
680 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
682 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
683 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
684 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
685 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
686 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
687 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
688 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
689 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
690 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
691 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
692 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
693 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
694 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
695 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
696 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
697 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
700 struct r_glsl_permutation_s;
701 typedef struct r_glsl_permutation_s
704 struct r_glsl_permutation_s *hashnext;
706 unsigned int permutation;
708 /// indicates if we have tried compiling this permutation already
710 /// 0 if compilation failed
712 // texture units assigned to each detected uniform
713 int tex_Texture_First;
714 int tex_Texture_Second;
715 int tex_Texture_GammaRamps;
716 int tex_Texture_Normal;
717 int tex_Texture_Color;
718 int tex_Texture_Gloss;
719 int tex_Texture_Glow;
720 int tex_Texture_SecondaryNormal;
721 int tex_Texture_SecondaryColor;
722 int tex_Texture_SecondaryGloss;
723 int tex_Texture_SecondaryGlow;
724 int tex_Texture_Pants;
725 int tex_Texture_Shirt;
726 int tex_Texture_FogHeightTexture;
727 int tex_Texture_FogMask;
728 int tex_Texture_Lightmap;
729 int tex_Texture_Deluxemap;
730 int tex_Texture_Attenuation;
731 int tex_Texture_Cube;
732 int tex_Texture_Refraction;
733 int tex_Texture_Reflection;
734 int tex_Texture_ShadowMap2D;
735 int tex_Texture_CubeProjection;
736 int tex_Texture_ScreenDepth;
737 int tex_Texture_ScreenNormalMap;
738 int tex_Texture_ScreenDiffuse;
739 int tex_Texture_ScreenSpecular;
740 int tex_Texture_ReflectMask;
741 int tex_Texture_ReflectCube;
742 int tex_Texture_BounceGrid;
743 /// locations of detected uniforms in program object, or -1 if not found
744 int loc_Texture_First;
745 int loc_Texture_Second;
746 int loc_Texture_GammaRamps;
747 int loc_Texture_Normal;
748 int loc_Texture_Color;
749 int loc_Texture_Gloss;
750 int loc_Texture_Glow;
751 int loc_Texture_SecondaryNormal;
752 int loc_Texture_SecondaryColor;
753 int loc_Texture_SecondaryGloss;
754 int loc_Texture_SecondaryGlow;
755 int loc_Texture_Pants;
756 int loc_Texture_Shirt;
757 int loc_Texture_FogHeightTexture;
758 int loc_Texture_FogMask;
759 int loc_Texture_Lightmap;
760 int loc_Texture_Deluxemap;
761 int loc_Texture_Attenuation;
762 int loc_Texture_Cube;
763 int loc_Texture_Refraction;
764 int loc_Texture_Reflection;
765 int loc_Texture_ShadowMap2D;
766 int loc_Texture_CubeProjection;
767 int loc_Texture_ScreenDepth;
768 int loc_Texture_ScreenNormalMap;
769 int loc_Texture_ScreenDiffuse;
770 int loc_Texture_ScreenSpecular;
771 int loc_Texture_ReflectMask;
772 int loc_Texture_ReflectCube;
773 int loc_Texture_BounceGrid;
775 int loc_BloomBlur_Parameters;
777 int loc_Color_Ambient;
778 int loc_Color_Diffuse;
779 int loc_Color_Specular;
783 int loc_DeferredColor_Ambient;
784 int loc_DeferredColor_Diffuse;
785 int loc_DeferredColor_Specular;
786 int loc_DeferredMod_Diffuse;
787 int loc_DeferredMod_Specular;
788 int loc_DistortScaleRefractReflect;
791 int loc_FogHeightFade;
793 int loc_FogPlaneViewDist;
794 int loc_FogRangeRecip;
797 int loc_LightPosition;
798 int loc_OffsetMapping_Scale;
800 int loc_ReflectColor;
801 int loc_ReflectFactor;
802 int loc_ReflectOffset;
803 int loc_RefractColor;
805 int loc_ScreenCenterRefractReflect;
806 int loc_ScreenScaleRefractReflect;
807 int loc_ScreenToDepth;
808 int loc_ShadowMap_Parameters;
809 int loc_ShadowMap_TextureScale;
810 int loc_SpecularPower;
815 int loc_ViewTintColor;
817 int loc_ModelToLight;
819 int loc_BackgroundTexMatrix;
820 int loc_ModelViewProjectionMatrix;
821 int loc_ModelViewMatrix;
822 int loc_PixelToScreenTexCoord;
823 int loc_ModelToReflectCube;
824 int loc_ShadowMapMatrix;
825 int loc_BloomColorSubtract;
826 int loc_NormalmapScrollBlend;
827 int loc_BounceGridMatrix;
828 int loc_BounceGridIntensity;
830 r_glsl_permutation_t;
832 #define SHADERPERMUTATION_HASHSIZE 256
835 // non-degradable "lightweight" shader parameters to keep the permutations simpler
836 // these can NOT degrade! only use for simple stuff
839 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
840 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
841 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
842 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
843 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
844 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
846 #define SHADERSTATICPARMS_COUNT 6
848 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
849 static int shaderstaticparms_count = 0;
851 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
852 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
853 qboolean R_CompileShader_CheckStaticParms(void)
855 static int r_compileshader_staticparms_save[1];
856 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
857 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
860 if (r_glsl_saturation_redcompensate.integer)
861 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
862 if (r_shadow_glossexact.integer)
863 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
864 if (r_glsl_postprocess.integer)
866 if (r_glsl_postprocess_uservec1_enable.integer)
867 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
868 if (r_glsl_postprocess_uservec2_enable.integer)
869 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
870 if (r_glsl_postprocess_uservec3_enable.integer)
871 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
872 if (r_glsl_postprocess_uservec4_enable.integer)
873 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
875 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
878 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
879 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
880 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
882 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
883 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
885 shaderstaticparms_count = 0;
888 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
889 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
890 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
891 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
892 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
893 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
896 /// information about each possible shader permutation
897 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
898 /// currently selected permutation
899 r_glsl_permutation_t *r_glsl_permutation;
900 /// storage for permutations linked in the hash table
901 memexpandablearray_t r_glsl_permutationarray;
903 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
905 //unsigned int hashdepth = 0;
906 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
907 r_glsl_permutation_t *p;
908 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
910 if (p->mode == mode && p->permutation == permutation)
912 //if (hashdepth > 10)
913 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
918 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
920 p->permutation = permutation;
921 p->hashnext = r_glsl_permutationhash[mode][hashindex];
922 r_glsl_permutationhash[mode][hashindex] = p;
923 //if (hashdepth > 10)
924 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
928 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
931 if (!filename || !filename[0])
933 if (!strcmp(filename, "glsl/default.glsl"))
935 if (!glslshaderstring)
937 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
938 if (glslshaderstring)
939 Con_DPrintf("Loading shaders from file %s...\n", filename);
941 glslshaderstring = (char *)builtinshaderstring;
943 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
944 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
947 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
950 if (printfromdisknotice)
951 Con_DPrintf("from disk %s... ", filename);
957 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
961 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
962 char *vertexstring, *geometrystring, *fragmentstring;
963 char permutationname[256];
964 int vertstrings_count = 0;
965 int geomstrings_count = 0;
966 int fragstrings_count = 0;
967 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
968 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
969 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
976 permutationname[0] = 0;
977 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
978 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
979 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
981 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
983 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
984 if(vid.support.gl20shaders130)
986 vertstrings_list[vertstrings_count++] = "#version 130\n";
987 geomstrings_list[geomstrings_count++] = "#version 130\n";
988 fragstrings_list[fragstrings_count++] = "#version 130\n";
991 // the first pretext is which type of shader to compile as
992 // (later these will all be bound together as a program object)
993 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
994 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
995 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
997 // the second pretext is the mode (for example a light source)
998 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
999 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1000 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1001 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1003 // now add all the permutation pretexts
1004 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1006 if (permutation & (1<<i))
1008 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1009 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1010 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1011 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1015 // keep line numbers correct
1016 vertstrings_list[vertstrings_count++] = "\n";
1017 geomstrings_list[geomstrings_count++] = "\n";
1018 fragstrings_list[fragstrings_count++] = "\n";
1023 R_CompileShader_AddStaticParms(mode, permutation);
1024 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1025 vertstrings_count += shaderstaticparms_count;
1026 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1027 geomstrings_count += shaderstaticparms_count;
1028 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1029 fragstrings_count += shaderstaticparms_count;
1031 // now append the shader text itself
1032 vertstrings_list[vertstrings_count++] = vertexstring;
1033 geomstrings_list[geomstrings_count++] = geometrystring;
1034 fragstrings_list[fragstrings_count++] = fragmentstring;
1036 // if any sources were NULL, clear the respective list
1038 vertstrings_count = 0;
1039 if (!geometrystring)
1040 geomstrings_count = 0;
1041 if (!fragmentstring)
1042 fragstrings_count = 0;
1044 // compile the shader program
1045 if (vertstrings_count + geomstrings_count + fragstrings_count)
1046 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1050 qglUseProgram(p->program);CHECKGLERROR
1051 // look up all the uniform variable names we care about, so we don't
1052 // have to look them up every time we set them
1054 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1055 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1056 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1057 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1058 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1059 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1060 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1061 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1062 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1063 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1064 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1065 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1066 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1067 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1068 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1069 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1070 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1071 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1072 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1073 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1074 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1075 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1076 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1077 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1078 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1079 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1080 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1081 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1082 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1083 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1084 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1085 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1086 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1087 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1088 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1089 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1090 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1091 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1092 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1093 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1094 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1095 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1096 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1097 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1098 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1099 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1100 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1101 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1102 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1103 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1104 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1105 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1106 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1107 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1108 p->loc_OffsetMapping_Scale = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
1109 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1110 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1111 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1112 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1113 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1114 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1115 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1116 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1117 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1118 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1119 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1120 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1121 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1122 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1123 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1124 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1125 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1126 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1127 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1128 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1129 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1130 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1131 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1132 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1133 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1134 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1135 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1136 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1137 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1138 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1139 // initialize the samplers to refer to the texture units we use
1140 p->tex_Texture_First = -1;
1141 p->tex_Texture_Second = -1;
1142 p->tex_Texture_GammaRamps = -1;
1143 p->tex_Texture_Normal = -1;
1144 p->tex_Texture_Color = -1;
1145 p->tex_Texture_Gloss = -1;
1146 p->tex_Texture_Glow = -1;
1147 p->tex_Texture_SecondaryNormal = -1;
1148 p->tex_Texture_SecondaryColor = -1;
1149 p->tex_Texture_SecondaryGloss = -1;
1150 p->tex_Texture_SecondaryGlow = -1;
1151 p->tex_Texture_Pants = -1;
1152 p->tex_Texture_Shirt = -1;
1153 p->tex_Texture_FogHeightTexture = -1;
1154 p->tex_Texture_FogMask = -1;
1155 p->tex_Texture_Lightmap = -1;
1156 p->tex_Texture_Deluxemap = -1;
1157 p->tex_Texture_Attenuation = -1;
1158 p->tex_Texture_Cube = -1;
1159 p->tex_Texture_Refraction = -1;
1160 p->tex_Texture_Reflection = -1;
1161 p->tex_Texture_ShadowMap2D = -1;
1162 p->tex_Texture_CubeProjection = -1;
1163 p->tex_Texture_ScreenDepth = -1;
1164 p->tex_Texture_ScreenNormalMap = -1;
1165 p->tex_Texture_ScreenDiffuse = -1;
1166 p->tex_Texture_ScreenSpecular = -1;
1167 p->tex_Texture_ReflectMask = -1;
1168 p->tex_Texture_ReflectCube = -1;
1169 p->tex_Texture_BounceGrid = -1;
1171 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1172 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1173 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1174 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1175 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1176 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1177 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1178 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1179 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1180 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1181 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1182 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1183 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1184 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1185 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1186 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1187 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1188 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1189 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1190 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1191 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1192 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1193 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1194 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1195 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1196 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1197 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1198 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1199 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1200 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1202 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1205 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1209 Mem_Free(vertexstring);
1211 Mem_Free(geometrystring);
1213 Mem_Free(fragmentstring);
1216 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1218 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1219 if (r_glsl_permutation != perm)
1221 r_glsl_permutation = perm;
1222 if (!r_glsl_permutation->program)
1224 if (!r_glsl_permutation->compiled)
1225 R_GLSL_CompilePermutation(perm, mode, permutation);
1226 if (!r_glsl_permutation->program)
1228 // remove features until we find a valid permutation
1230 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1232 // reduce i more quickly whenever it would not remove any bits
1233 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1234 if (!(permutation & j))
1237 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1238 if (!r_glsl_permutation->compiled)
1239 R_GLSL_CompilePermutation(perm, mode, permutation);
1240 if (r_glsl_permutation->program)
1243 if (i >= SHADERPERMUTATION_COUNT)
1245 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1246 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1247 qglUseProgram(0);CHECKGLERROR
1248 return; // no bit left to clear, entire mode is broken
1253 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1255 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1256 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1257 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1264 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1265 extern D3DCAPS9 vid_d3d9caps;
1268 struct r_hlsl_permutation_s;
1269 typedef struct r_hlsl_permutation_s
1271 /// hash lookup data
1272 struct r_hlsl_permutation_s *hashnext;
1274 unsigned int permutation;
1276 /// indicates if we have tried compiling this permutation already
1278 /// NULL if compilation failed
1279 IDirect3DVertexShader9 *vertexshader;
1280 IDirect3DPixelShader9 *pixelshader;
1282 r_hlsl_permutation_t;
1284 typedef enum D3DVSREGISTER_e
1286 D3DVSREGISTER_TexMatrix = 0, // float4x4
1287 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1288 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1289 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1290 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1291 D3DVSREGISTER_ModelToLight = 20, // float4x4
1292 D3DVSREGISTER_EyePosition = 24,
1293 D3DVSREGISTER_FogPlane = 25,
1294 D3DVSREGISTER_LightDir = 26,
1295 D3DVSREGISTER_LightPosition = 27,
1299 typedef enum D3DPSREGISTER_e
1301 D3DPSREGISTER_Alpha = 0,
1302 D3DPSREGISTER_BloomBlur_Parameters = 1,
1303 D3DPSREGISTER_ClientTime = 2,
1304 D3DPSREGISTER_Color_Ambient = 3,
1305 D3DPSREGISTER_Color_Diffuse = 4,
1306 D3DPSREGISTER_Color_Specular = 5,
1307 D3DPSREGISTER_Color_Glow = 6,
1308 D3DPSREGISTER_Color_Pants = 7,
1309 D3DPSREGISTER_Color_Shirt = 8,
1310 D3DPSREGISTER_DeferredColor_Ambient = 9,
1311 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1312 D3DPSREGISTER_DeferredColor_Specular = 11,
1313 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1314 D3DPSREGISTER_DeferredMod_Specular = 13,
1315 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1316 D3DPSREGISTER_EyePosition = 15, // unused
1317 D3DPSREGISTER_FogColor = 16,
1318 D3DPSREGISTER_FogHeightFade = 17,
1319 D3DPSREGISTER_FogPlane = 18,
1320 D3DPSREGISTER_FogPlaneViewDist = 19,
1321 D3DPSREGISTER_FogRangeRecip = 20,
1322 D3DPSREGISTER_LightColor = 21,
1323 D3DPSREGISTER_LightDir = 22, // unused
1324 D3DPSREGISTER_LightPosition = 23,
1325 D3DPSREGISTER_OffsetMapping_Scale = 24,
1326 D3DPSREGISTER_PixelSize = 25,
1327 D3DPSREGISTER_ReflectColor = 26,
1328 D3DPSREGISTER_ReflectFactor = 27,
1329 D3DPSREGISTER_ReflectOffset = 28,
1330 D3DPSREGISTER_RefractColor = 29,
1331 D3DPSREGISTER_Saturation = 30,
1332 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1333 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1334 D3DPSREGISTER_ScreenToDepth = 33,
1335 D3DPSREGISTER_ShadowMap_Parameters = 34,
1336 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1337 D3DPSREGISTER_SpecularPower = 36,
1338 D3DPSREGISTER_UserVec1 = 37,
1339 D3DPSREGISTER_UserVec2 = 38,
1340 D3DPSREGISTER_UserVec3 = 39,
1341 D3DPSREGISTER_UserVec4 = 40,
1342 D3DPSREGISTER_ViewTintColor = 41,
1343 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1344 D3DPSREGISTER_BloomColorSubtract = 43,
1345 D3DPSREGISTER_ViewToLight = 44, // float4x4
1346 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1347 D3DPSREGISTER_NormalmapScrollBlend = 52,
1352 /// information about each possible shader permutation
1353 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1354 /// currently selected permutation
1355 r_hlsl_permutation_t *r_hlsl_permutation;
1356 /// storage for permutations linked in the hash table
1357 memexpandablearray_t r_hlsl_permutationarray;
1359 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1361 //unsigned int hashdepth = 0;
1362 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1363 r_hlsl_permutation_t *p;
1364 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1366 if (p->mode == mode && p->permutation == permutation)
1368 //if (hashdepth > 10)
1369 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1374 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1376 p->permutation = permutation;
1377 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1378 r_hlsl_permutationhash[mode][hashindex] = p;
1379 //if (hashdepth > 10)
1380 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1384 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1387 if (!filename || !filename[0])
1389 if (!strcmp(filename, "hlsl/default.hlsl"))
1391 if (!hlslshaderstring)
1393 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1394 if (hlslshaderstring)
1395 Con_DPrintf("Loading shaders from file %s...\n", filename);
1397 hlslshaderstring = (char *)builtinhlslshaderstring;
1399 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1400 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1401 return shaderstring;
1403 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1406 if (printfromdisknotice)
1407 Con_DPrintf("from disk %s... ", filename);
1408 return shaderstring;
1410 return shaderstring;
1414 //#include <d3dx9shader.h>
1415 //#include <d3dx9mesh.h>
1417 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1419 DWORD *vsbin = NULL;
1420 DWORD *psbin = NULL;
1421 fs_offset_t vsbinsize;
1422 fs_offset_t psbinsize;
1423 // IDirect3DVertexShader9 *vs = NULL;
1424 // IDirect3DPixelShader9 *ps = NULL;
1425 ID3DXBuffer *vslog = NULL;
1426 ID3DXBuffer *vsbuffer = NULL;
1427 ID3DXConstantTable *vsconstanttable = NULL;
1428 ID3DXBuffer *pslog = NULL;
1429 ID3DXBuffer *psbuffer = NULL;
1430 ID3DXConstantTable *psconstanttable = NULL;
1433 char temp[MAX_INPUTLINE];
1434 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1435 qboolean debugshader = gl_paranoid.integer != 0;
1436 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1437 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1440 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1441 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1443 if ((!vsbin && vertstring) || (!psbin && fragstring))
1445 const char* dllnames_d3dx9 [] =
1469 dllhandle_t d3dx9_dll = NULL;
1470 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1471 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1472 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1473 dllfunction_t d3dx9_dllfuncs[] =
1475 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1476 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1477 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1480 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1482 DWORD shaderflags = 0;
1484 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1485 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1486 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1487 if (vertstring && vertstring[0])
1491 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1492 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1493 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1494 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1497 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1500 vsbinsize = vsbuffer->GetBufferSize();
1501 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1502 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1503 vsbuffer->Release();
1507 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1508 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1512 if (fragstring && fragstring[0])
1516 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1517 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1518 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1519 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1522 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1525 psbinsize = psbuffer->GetBufferSize();
1526 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1527 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1528 psbuffer->Release();
1532 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1533 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1537 Sys_UnloadLibrary(&d3dx9_dll);
1540 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1544 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1545 if (FAILED(vsresult))
1546 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1547 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1548 if (FAILED(psresult))
1549 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1551 // free the shader data
1552 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1553 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1556 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1559 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1560 int vertstring_length = 0;
1561 int geomstring_length = 0;
1562 int fragstring_length = 0;
1564 char *vertexstring, *geometrystring, *fragmentstring;
1565 char *vertstring, *geomstring, *fragstring;
1566 char permutationname[256];
1567 char cachename[256];
1568 int vertstrings_count = 0;
1569 int geomstrings_count = 0;
1570 int fragstrings_count = 0;
1571 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1572 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1573 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1578 p->vertexshader = NULL;
1579 p->pixelshader = NULL;
1581 permutationname[0] = 0;
1583 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1584 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1585 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1587 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1588 strlcat(cachename, "hlsl/", sizeof(cachename));
1590 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1591 vertstrings_count = 0;
1592 geomstrings_count = 0;
1593 fragstrings_count = 0;
1594 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1595 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1596 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1598 // the first pretext is which type of shader to compile as
1599 // (later these will all be bound together as a program object)
1600 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1601 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1602 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1604 // the second pretext is the mode (for example a light source)
1605 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1606 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1607 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1608 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1609 strlcat(cachename, modeinfo->name, sizeof(cachename));
1611 // now add all the permutation pretexts
1612 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1614 if (permutation & (1<<i))
1616 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1617 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1618 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1619 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1620 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1624 // keep line numbers correct
1625 vertstrings_list[vertstrings_count++] = "\n";
1626 geomstrings_list[geomstrings_count++] = "\n";
1627 fragstrings_list[fragstrings_count++] = "\n";
1632 R_CompileShader_AddStaticParms(mode, permutation);
1633 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1634 vertstrings_count += shaderstaticparms_count;
1635 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1636 geomstrings_count += shaderstaticparms_count;
1637 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1638 fragstrings_count += shaderstaticparms_count;
1640 // replace spaces in the cachename with _ characters
1641 for (i = 0;cachename[i];i++)
1642 if (cachename[i] == ' ')
1645 // now append the shader text itself
1646 vertstrings_list[vertstrings_count++] = vertexstring;
1647 geomstrings_list[geomstrings_count++] = geometrystring;
1648 fragstrings_list[fragstrings_count++] = fragmentstring;
1650 // if any sources were NULL, clear the respective list
1652 vertstrings_count = 0;
1653 if (!geometrystring)
1654 geomstrings_count = 0;
1655 if (!fragmentstring)
1656 fragstrings_count = 0;
1658 vertstring_length = 0;
1659 for (i = 0;i < vertstrings_count;i++)
1660 vertstring_length += strlen(vertstrings_list[i]);
1661 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1662 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1663 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1665 geomstring_length = 0;
1666 for (i = 0;i < geomstrings_count;i++)
1667 geomstring_length += strlen(geomstrings_list[i]);
1668 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1669 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1670 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1672 fragstring_length = 0;
1673 for (i = 0;i < fragstrings_count;i++)
1674 fragstring_length += strlen(fragstrings_list[i]);
1675 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1676 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1677 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1679 // try to load the cached shader, or generate one
1680 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1682 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1683 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1685 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1689 Mem_Free(vertstring);
1691 Mem_Free(geomstring);
1693 Mem_Free(fragstring);
1695 Mem_Free(vertexstring);
1697 Mem_Free(geometrystring);
1699 Mem_Free(fragmentstring);
1702 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1703 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1704 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);}
1705 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);}
1706 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);}
1707 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1709 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1710 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1711 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);}
1712 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);}
1713 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);}
1714 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1716 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1718 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1719 if (r_hlsl_permutation != perm)
1721 r_hlsl_permutation = perm;
1722 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1724 if (!r_hlsl_permutation->compiled)
1725 R_HLSL_CompilePermutation(perm, mode, permutation);
1726 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1728 // remove features until we find a valid permutation
1730 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1732 // reduce i more quickly whenever it would not remove any bits
1733 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1734 if (!(permutation & j))
1737 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1738 if (!r_hlsl_permutation->compiled)
1739 R_HLSL_CompilePermutation(perm, mode, permutation);
1740 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1743 if (i >= SHADERPERMUTATION_COUNT)
1745 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1746 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1747 return; // no bit left to clear, entire mode is broken
1751 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1752 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1754 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1755 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1756 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1760 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1762 DPSOFTRAST_SetShader(mode, permutation);
1763 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1764 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1765 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1768 void R_GLSL_Restart_f(void)
1770 unsigned int i, limit;
1771 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1772 Mem_Free(glslshaderstring);
1773 glslshaderstring = NULL;
1774 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1775 Mem_Free(hlslshaderstring);
1776 hlslshaderstring = NULL;
1777 switch(vid.renderpath)
1779 case RENDERPATH_D3D9:
1782 r_hlsl_permutation_t *p;
1783 r_hlsl_permutation = NULL;
1784 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1785 for (i = 0;i < limit;i++)
1787 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1789 if (p->vertexshader)
1790 IDirect3DVertexShader9_Release(p->vertexshader);
1792 IDirect3DPixelShader9_Release(p->pixelshader);
1793 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1796 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1800 case RENDERPATH_D3D10:
1801 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1803 case RENDERPATH_D3D11:
1804 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1806 case RENDERPATH_GL20:
1807 case RENDERPATH_GLES2:
1809 r_glsl_permutation_t *p;
1810 r_glsl_permutation = NULL;
1811 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1812 for (i = 0;i < limit;i++)
1814 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1816 GL_Backend_FreeProgram(p->program);
1817 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1820 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1823 case RENDERPATH_GL13:
1824 case RENDERPATH_GL11:
1826 case RENDERPATH_SOFT:
1831 void R_GLSL_DumpShader_f(void)
1836 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1839 FS_Print(file, "/* The engine may define the following macros:\n");
1840 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1841 for (i = 0;i < SHADERMODE_COUNT;i++)
1842 FS_Print(file, glslshadermodeinfo[i].pretext);
1843 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1844 FS_Print(file, shaderpermutationinfo[i].pretext);
1845 FS_Print(file, "*/\n");
1846 FS_Print(file, builtinshaderstring);
1848 Con_Printf("glsl/default.glsl written\n");
1851 Con_Printf("failed to write to glsl/default.glsl\n");
1853 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1856 FS_Print(file, "/* The engine may define the following macros:\n");
1857 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1858 for (i = 0;i < SHADERMODE_COUNT;i++)
1859 FS_Print(file, hlslshadermodeinfo[i].pretext);
1860 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1861 FS_Print(file, shaderpermutationinfo[i].pretext);
1862 FS_Print(file, "*/\n");
1863 FS_Print(file, builtinhlslshaderstring);
1865 Con_Printf("hlsl/default.hlsl written\n");
1868 Con_Printf("failed to write to hlsl/default.hlsl\n");
1871 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1874 texturemode = GL_MODULATE;
1875 switch (vid.renderpath)
1877 case RENDERPATH_D3D9:
1879 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))));
1880 R_Mesh_TexBind(GL20TU_FIRST , first );
1881 R_Mesh_TexBind(GL20TU_SECOND, second);
1884 case RENDERPATH_D3D10:
1885 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1887 case RENDERPATH_D3D11:
1888 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1890 case RENDERPATH_GL20:
1891 case RENDERPATH_GLES2:
1892 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))));
1893 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1894 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1896 case RENDERPATH_GL13:
1897 R_Mesh_TexBind(0, first );
1898 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1899 R_Mesh_TexBind(1, second);
1901 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1903 case RENDERPATH_GL11:
1904 R_Mesh_TexBind(0, first );
1906 case RENDERPATH_SOFT:
1907 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))));
1908 R_Mesh_TexBind(GL20TU_FIRST , first );
1909 R_Mesh_TexBind(GL20TU_SECOND, second);
1914 void R_SetupShader_DepthOrShadow(void)
1916 switch (vid.renderpath)
1918 case RENDERPATH_D3D9:
1920 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1923 case RENDERPATH_D3D10:
1924 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1926 case RENDERPATH_D3D11:
1927 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1929 case RENDERPATH_GL20:
1930 case RENDERPATH_GLES2:
1931 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1933 case RENDERPATH_GL13:
1934 R_Mesh_TexBind(0, 0);
1935 R_Mesh_TexBind(1, 0);
1937 case RENDERPATH_GL11:
1938 R_Mesh_TexBind(0, 0);
1940 case RENDERPATH_SOFT:
1941 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1946 void R_SetupShader_ShowDepth(void)
1948 switch (vid.renderpath)
1950 case RENDERPATH_D3D9:
1952 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1955 case RENDERPATH_D3D10:
1956 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958 case RENDERPATH_D3D11:
1959 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961 case RENDERPATH_GL20:
1962 case RENDERPATH_GLES2:
1963 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1965 case RENDERPATH_GL13:
1967 case RENDERPATH_GL11:
1969 case RENDERPATH_SOFT:
1970 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1975 extern qboolean r_shadow_usingdeferredprepass;
1976 extern cvar_t r_shadow_deferred_8bitrange;
1977 extern rtexture_t *r_shadow_attenuationgradienttexture;
1978 extern rtexture_t *r_shadow_attenuation2dtexture;
1979 extern rtexture_t *r_shadow_attenuation3dtexture;
1980 extern qboolean r_shadow_usingshadowmap2d;
1981 extern qboolean r_shadow_usingshadowmaportho;
1982 extern float r_shadow_shadowmap_texturescale[2];
1983 extern float r_shadow_shadowmap_parameters[4];
1984 extern qboolean r_shadow_shadowmapvsdct;
1985 extern qboolean r_shadow_shadowmapsampler;
1986 extern int r_shadow_shadowmappcf;
1987 extern rtexture_t *r_shadow_shadowmap2dtexture;
1988 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1989 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1990 extern matrix4x4_t r_shadow_shadowmapmatrix;
1991 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1992 extern int r_shadow_prepass_width;
1993 extern int r_shadow_prepass_height;
1994 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1995 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1996 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
1997 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
1998 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2000 #define BLENDFUNC_ALLOWS_COLORMOD 1
2001 #define BLENDFUNC_ALLOWS_FOG 2
2002 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2003 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2004 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2005 static int R_BlendFuncFlags(int src, int dst)
2009 // a blendfunc allows colormod if:
2010 // a) it can never keep the destination pixel invariant, or
2011 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2012 // this is to prevent unintended side effects from colormod
2014 // a blendfunc allows fog if:
2015 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2016 // this is to prevent unintended side effects from fog
2018 // these checks are the output of fogeval.pl
2020 r |= BLENDFUNC_ALLOWS_COLORMOD;
2021 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2022 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2023 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2024 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2025 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2026 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2027 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2028 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2029 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2030 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2031 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2032 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2033 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2034 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2035 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2036 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2037 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2038 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2039 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2040 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2041 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2046 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
2048 // select a permutation of the lighting shader appropriate to this
2049 // combination of texture, entity, light source, and fogging, only use the
2050 // minimum features necessary to avoid wasting rendering time in the
2051 // fragment shader on features that are not being used
2052 unsigned int permutation = 0;
2053 unsigned int mode = 0;
2055 static float dummy_colormod[3] = {1, 1, 1};
2056 float *colormod = rsurface.colormod;
2058 matrix4x4_t tempmatrix;
2059 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2060 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2061 permutation |= SHADERPERMUTATION_ALPHAKILL;
2062 if (rsurfacepass == RSURFPASS_BACKGROUND)
2064 // distorted background
2065 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2067 mode = SHADERMODE_WATER;
2068 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2069 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2070 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2072 // this is the right thing to do for wateralpha
2073 GL_BlendFunc(GL_ONE, GL_ZERO);
2074 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2078 // this is the right thing to do for entity alpha
2079 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2080 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2083 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2085 mode = SHADERMODE_REFRACTION;
2086 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2087 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2091 mode = SHADERMODE_GENERIC;
2092 permutation |= SHADERPERMUTATION_DIFFUSE;
2093 GL_BlendFunc(GL_ONE, GL_ZERO);
2094 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2097 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2099 if (r_glsl_offsetmapping.integer)
2101 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2102 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2103 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2104 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2105 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2107 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2108 if (r_glsl_offsetmapping_reliefmapping.integer)
2109 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2112 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2113 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2114 // normalmap (deferred prepass), may use alpha test on diffuse
2115 mode = SHADERMODE_DEFERREDGEOMETRY;
2116 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2117 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2118 GL_BlendFunc(GL_ONE, GL_ZERO);
2119 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2121 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2123 if (r_glsl_offsetmapping.integer)
2125 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2126 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2127 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2128 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2129 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2131 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2132 if (r_glsl_offsetmapping_reliefmapping.integer)
2133 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2136 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2137 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2139 mode = SHADERMODE_LIGHTSOURCE;
2140 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2141 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2142 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2143 permutation |= SHADERPERMUTATION_CUBEFILTER;
2144 if (diffusescale > 0)
2145 permutation |= SHADERPERMUTATION_DIFFUSE;
2146 if (specularscale > 0)
2147 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2148 if (r_refdef.fogenabled)
2149 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2150 if (rsurface.texture->colormapping)
2151 permutation |= SHADERPERMUTATION_COLORMAPPING;
2152 if (r_shadow_usingshadowmap2d)
2154 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2155 if(r_shadow_shadowmapvsdct)
2156 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2158 if (r_shadow_shadowmapsampler)
2159 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2160 if (r_shadow_shadowmappcf > 1)
2161 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2162 else if (r_shadow_shadowmappcf)
2163 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2165 if (rsurface.texture->reflectmasktexture)
2166 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2167 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2168 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2170 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2172 if (r_glsl_offsetmapping.integer)
2174 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2175 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2176 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2177 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2178 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2180 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2181 if (r_glsl_offsetmapping_reliefmapping.integer)
2182 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2185 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2186 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2187 // unshaded geometry (fullbright or ambient model lighting)
2188 mode = SHADERMODE_FLATCOLOR;
2189 ambientscale = diffusescale = specularscale = 0;
2190 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2191 permutation |= SHADERPERMUTATION_GLOW;
2192 if (r_refdef.fogenabled)
2193 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2194 if (rsurface.texture->colormapping)
2195 permutation |= SHADERPERMUTATION_COLORMAPPING;
2196 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2198 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2199 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2201 if (r_shadow_shadowmapsampler)
2202 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2203 if (r_shadow_shadowmappcf > 1)
2204 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2205 else if (r_shadow_shadowmappcf)
2206 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2208 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2209 permutation |= SHADERPERMUTATION_REFLECTION;
2210 if (rsurface.texture->reflectmasktexture)
2211 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2212 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2213 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2215 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2217 if (r_glsl_offsetmapping.integer)
2219 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2220 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2221 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2222 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2223 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2225 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2226 if (r_glsl_offsetmapping_reliefmapping.integer)
2227 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2230 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2231 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2232 // directional model lighting
2233 mode = SHADERMODE_LIGHTDIRECTION;
2234 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2235 permutation |= SHADERPERMUTATION_GLOW;
2236 permutation |= SHADERPERMUTATION_DIFFUSE;
2237 if (specularscale > 0)
2238 permutation |= SHADERPERMUTATION_SPECULAR;
2239 if (r_refdef.fogenabled)
2240 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2241 if (rsurface.texture->colormapping)
2242 permutation |= SHADERPERMUTATION_COLORMAPPING;
2243 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2245 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2246 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2248 if (r_shadow_shadowmapsampler)
2249 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2250 if (r_shadow_shadowmappcf > 1)
2251 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2252 else if (r_shadow_shadowmappcf)
2253 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2255 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2256 permutation |= SHADERPERMUTATION_REFLECTION;
2257 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2258 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2259 if (rsurface.texture->reflectmasktexture)
2260 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2261 if (r_shadow_bouncegridtexture)
2262 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2263 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2264 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2266 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2268 if (r_glsl_offsetmapping.integer)
2270 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2271 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2272 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2273 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2274 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2276 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2277 if (r_glsl_offsetmapping_reliefmapping.integer)
2278 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2281 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2282 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2283 // ambient model lighting
2284 mode = SHADERMODE_LIGHTDIRECTION;
2285 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2286 permutation |= SHADERPERMUTATION_GLOW;
2287 if (r_refdef.fogenabled)
2288 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2289 if (rsurface.texture->colormapping)
2290 permutation |= SHADERPERMUTATION_COLORMAPPING;
2291 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2293 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2294 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2296 if (r_shadow_shadowmapsampler)
2297 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2298 if (r_shadow_shadowmappcf > 1)
2299 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2300 else if (r_shadow_shadowmappcf)
2301 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2303 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2304 permutation |= SHADERPERMUTATION_REFLECTION;
2305 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2306 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2307 if (rsurface.texture->reflectmasktexture)
2308 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2309 if (r_shadow_bouncegridtexture)
2310 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2311 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2312 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2316 if (r_glsl_offsetmapping.integer)
2318 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2319 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2320 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2321 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2322 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2324 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2325 if (r_glsl_offsetmapping_reliefmapping.integer)
2326 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2329 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2330 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2332 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2333 permutation |= SHADERPERMUTATION_GLOW;
2334 if (r_refdef.fogenabled)
2335 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2336 if (rsurface.texture->colormapping)
2337 permutation |= SHADERPERMUTATION_COLORMAPPING;
2338 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2340 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2341 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2343 if (r_shadow_shadowmapsampler)
2344 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2345 if (r_shadow_shadowmappcf > 1)
2346 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2347 else if (r_shadow_shadowmappcf)
2348 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2350 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2351 permutation |= SHADERPERMUTATION_REFLECTION;
2352 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2353 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2354 if (rsurface.texture->reflectmasktexture)
2355 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2356 if (FAKELIGHT_ENABLED)
2358 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2359 mode = SHADERMODE_FAKELIGHT;
2360 permutation |= SHADERPERMUTATION_DIFFUSE;
2361 if (specularscale > 0)
2362 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2364 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2366 // deluxemapping (light direction texture)
2367 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2368 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2370 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2371 permutation |= SHADERPERMUTATION_DIFFUSE;
2372 if (specularscale > 0)
2373 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2375 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2377 // fake deluxemapping (uniform light direction in tangentspace)
2378 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2379 permutation |= SHADERPERMUTATION_DIFFUSE;
2380 if (specularscale > 0)
2381 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2383 else if (rsurface.uselightmaptexture)
2385 // ordinary lightmapping (q1bsp, q3bsp)
2386 mode = SHADERMODE_LIGHTMAP;
2390 // ordinary vertex coloring (q3bsp)
2391 mode = SHADERMODE_VERTEXCOLOR;
2393 if (r_shadow_bouncegridtexture)
2394 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2395 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2396 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2398 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2399 colormod = dummy_colormod;
2400 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2401 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2402 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2403 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2404 switch(vid.renderpath)
2406 case RENDERPATH_D3D9:
2408 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);
2409 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2410 R_SetupShader_SetPermutationHLSL(mode, permutation);
2411 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2412 if (mode == SHADERMODE_LIGHTSOURCE)
2414 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2415 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2419 if (mode == SHADERMODE_LIGHTDIRECTION)
2421 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2424 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2425 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2426 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2427 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2428 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2430 if (mode == SHADERMODE_LIGHTSOURCE)
2432 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2433 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2434 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2435 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2436 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2438 // additive passes are only darkened by fog, not tinted
2439 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2440 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2444 if (mode == SHADERMODE_FLATCOLOR)
2446 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2448 else if (mode == SHADERMODE_LIGHTDIRECTION)
2450 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]);
2451 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2452 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);
2453 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);
2454 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2455 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2456 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2460 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2461 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2462 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);
2463 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);
2464 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2466 // additive passes are only darkened by fog, not tinted
2467 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2468 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2470 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2471 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);
2472 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2473 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2474 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2475 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2476 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2477 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2478 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2479 if (mode == SHADERMODE_WATER)
2480 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2482 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2483 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2484 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2485 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));
2486 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2487 if (rsurface.texture->pantstexture)
2488 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2490 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2491 if (rsurface.texture->shirttexture)
2492 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2494 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2495 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2496 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2497 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2498 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2499 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2500 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2501 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2503 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2504 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2505 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2506 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2507 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2508 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2509 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2510 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2511 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2512 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2513 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2514 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2515 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2516 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2517 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2518 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2519 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2520 if (rsurfacepass == RSURFPASS_BACKGROUND)
2522 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2523 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2524 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2528 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2530 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2531 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2532 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2533 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2534 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2536 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2537 if (rsurface.rtlight)
2539 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2540 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2545 case RENDERPATH_D3D10:
2546 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2548 case RENDERPATH_D3D11:
2549 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2551 case RENDERPATH_GL20:
2552 case RENDERPATH_GLES2:
2553 if (!vid.useinterleavedarrays)
2555 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);
2556 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2557 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2558 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2559 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2560 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2561 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2562 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2566 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);
2567 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2569 R_SetupShader_SetPermutationGLSL(mode, permutation);
2570 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2571 if (mode == SHADERMODE_LIGHTSOURCE)
2573 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2574 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2575 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2576 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2577 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2578 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2580 // additive passes are only darkened by fog, not tinted
2581 if (r_glsl_permutation->loc_FogColor >= 0)
2582 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2583 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2587 if (mode == SHADERMODE_FLATCOLOR)
2589 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2591 else if (mode == SHADERMODE_LIGHTDIRECTION)
2593 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]);
2594 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]);
2595 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);
2596 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);
2597 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);
2598 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]);
2599 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]);
2603 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]);
2604 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]);
2605 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);
2606 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);
2607 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2609 // additive passes are only darkened by fog, not tinted
2610 if (r_glsl_permutation->loc_FogColor >= 0)
2612 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2613 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2615 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2617 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);
2618 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]);
2619 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]);
2620 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]);
2621 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]);
2622 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2623 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2624 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2625 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2627 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2628 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2629 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2630 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]);
2631 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2633 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2634 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));
2635 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2636 if (r_glsl_permutation->loc_Color_Pants >= 0)
2638 if (rsurface.texture->pantstexture)
2639 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2641 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2643 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2645 if (rsurface.texture->shirttexture)
2646 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2648 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2650 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]);
2651 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2652 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2653 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2654 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2655 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]);
2656 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2657 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);}
2658 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2660 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2661 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2662 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2663 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2664 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2665 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2666 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2667 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2668 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2669 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2670 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2671 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2672 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2673 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2674 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);
2675 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2676 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2677 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2678 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2679 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2680 if (rsurfacepass == RSURFPASS_BACKGROUND)
2682 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);
2683 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);
2684 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);
2688 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2690 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2691 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2692 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2693 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2694 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2696 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2697 if (rsurface.rtlight)
2699 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2700 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2703 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2706 case RENDERPATH_GL13:
2707 case RENDERPATH_GL11:
2709 case RENDERPATH_SOFT:
2710 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);
2711 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2712 R_SetupShader_SetPermutationSoft(mode, permutation);
2713 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2714 if (mode == SHADERMODE_LIGHTSOURCE)
2716 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2717 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2718 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2719 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2720 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2721 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2723 // additive passes are only darkened by fog, not tinted
2724 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2725 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2729 if (mode == SHADERMODE_FLATCOLOR)
2731 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2733 else if (mode == SHADERMODE_LIGHTDIRECTION)
2735 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]);
2736 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2737 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);
2738 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);
2739 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2740 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]);
2741 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2745 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2746 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2747 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);
2748 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);
2749 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2751 // additive passes are only darkened by fog, not tinted
2752 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2753 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2755 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2756 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);
2757 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2758 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2759 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]);
2760 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]);
2761 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2762 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2763 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2764 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2766 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2767 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2768 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2769 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2770 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2772 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2773 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));
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2775 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2777 if (rsurface.texture->pantstexture)
2778 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2780 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2782 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2784 if (rsurface.texture->shirttexture)
2785 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2787 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2789 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2790 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2791 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2792 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2793 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2794 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2795 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2797 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2798 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2799 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2800 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2801 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2802 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2803 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2804 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2805 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2806 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2807 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2808 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2809 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2810 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2811 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2812 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2813 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2814 if (rsurfacepass == RSURFPASS_BACKGROUND)
2816 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2817 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2818 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2822 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2824 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2825 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2826 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2827 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2828 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2830 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2831 if (rsurface.rtlight)
2833 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2834 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2841 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2843 // select a permutation of the lighting shader appropriate to this
2844 // combination of texture, entity, light source, and fogging, only use the
2845 // minimum features necessary to avoid wasting rendering time in the
2846 // fragment shader on features that are not being used
2847 unsigned int permutation = 0;
2848 unsigned int mode = 0;
2849 const float *lightcolorbase = rtlight->currentcolor;
2850 float ambientscale = rtlight->ambientscale;
2851 float diffusescale = rtlight->diffusescale;
2852 float specularscale = rtlight->specularscale;
2853 // this is the location of the light in view space
2854 vec3_t viewlightorigin;
2855 // this transforms from view space (camera) to light space (cubemap)
2856 matrix4x4_t viewtolight;
2857 matrix4x4_t lighttoview;
2858 float viewtolight16f[16];
2859 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2861 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2862 if (rtlight->currentcubemap != r_texture_whitecube)
2863 permutation |= SHADERPERMUTATION_CUBEFILTER;
2864 if (diffusescale > 0)
2865 permutation |= SHADERPERMUTATION_DIFFUSE;
2866 if (specularscale > 0)
2867 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2868 if (r_shadow_usingshadowmap2d)
2870 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2871 if (r_shadow_shadowmapvsdct)
2872 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2874 if (r_shadow_shadowmapsampler)
2875 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2876 if (r_shadow_shadowmappcf > 1)
2877 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2878 else if (r_shadow_shadowmappcf)
2879 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2881 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2882 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2883 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2884 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2885 switch(vid.renderpath)
2887 case RENDERPATH_D3D9:
2889 R_SetupShader_SetPermutationHLSL(mode, permutation);
2890 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2891 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2892 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2893 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2894 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2895 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2896 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2897 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2898 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2899 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2901 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2902 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2903 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2904 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2905 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2906 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2909 case RENDERPATH_D3D10:
2910 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2912 case RENDERPATH_D3D11:
2913 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2915 case RENDERPATH_GL20:
2916 case RENDERPATH_GLES2:
2917 R_SetupShader_SetPermutationGLSL(mode, permutation);
2918 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2919 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2920 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);
2921 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);
2922 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);
2923 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]);
2924 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]);
2925 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));
2926 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]);
2927 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2929 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2930 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2931 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2932 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2933 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2934 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2936 case RENDERPATH_GL13:
2937 case RENDERPATH_GL11:
2939 case RENDERPATH_SOFT:
2940 R_SetupShader_SetPermutationGLSL(mode, permutation);
2941 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2942 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2943 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2944 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2945 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2946 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2947 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]);
2948 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));
2949 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2950 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2952 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2953 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2954 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2955 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2956 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2957 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2962 #define SKINFRAME_HASH 1024
2966 int loadsequence; // incremented each level change
2967 memexpandablearray_t array;
2968 skinframe_t *hash[SKINFRAME_HASH];
2971 r_skinframe_t r_skinframe;
2973 void R_SkinFrame_PrepareForPurge(void)
2975 r_skinframe.loadsequence++;
2976 // wrap it without hitting zero
2977 if (r_skinframe.loadsequence >= 200)
2978 r_skinframe.loadsequence = 1;
2981 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2985 // mark the skinframe as used for the purging code
2986 skinframe->loadsequence = r_skinframe.loadsequence;
2989 void R_SkinFrame_Purge(void)
2993 for (i = 0;i < SKINFRAME_HASH;i++)
2995 for (s = r_skinframe.hash[i];s;s = s->next)
2997 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2999 if (s->merged == s->base)
3001 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3002 R_PurgeTexture(s->stain );s->stain = NULL;
3003 R_PurgeTexture(s->merged);s->merged = NULL;
3004 R_PurgeTexture(s->base );s->base = NULL;
3005 R_PurgeTexture(s->pants );s->pants = NULL;
3006 R_PurgeTexture(s->shirt );s->shirt = NULL;
3007 R_PurgeTexture(s->nmap );s->nmap = NULL;
3008 R_PurgeTexture(s->gloss );s->gloss = NULL;
3009 R_PurgeTexture(s->glow );s->glow = NULL;
3010 R_PurgeTexture(s->fog );s->fog = NULL;
3011 R_PurgeTexture(s->reflect);s->reflect = NULL;
3012 s->loadsequence = 0;
3018 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3020 char basename[MAX_QPATH];
3022 Image_StripImageExtension(name, basename, sizeof(basename));
3024 if( last == NULL ) {
3026 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3027 item = r_skinframe.hash[hashindex];
3032 // linearly search through the hash bucket
3033 for( ; item ; item = item->next ) {
3034 if( !strcmp( item->basename, basename ) ) {
3041 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3045 char basename[MAX_QPATH];
3047 Image_StripImageExtension(name, basename, sizeof(basename));
3049 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3050 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3051 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3055 rtexture_t *dyntexture;
3056 // check whether its a dynamic texture
3057 dyntexture = CL_GetDynTexture( basename );
3058 if (!add && !dyntexture)
3060 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3061 memset(item, 0, sizeof(*item));
3062 strlcpy(item->basename, basename, sizeof(item->basename));
3063 item->base = dyntexture; // either NULL or dyntexture handle
3064 item->textureflags = textureflags;
3065 item->comparewidth = comparewidth;
3066 item->compareheight = compareheight;
3067 item->comparecrc = comparecrc;
3068 item->next = r_skinframe.hash[hashindex];
3069 r_skinframe.hash[hashindex] = item;
3071 else if( item->base == NULL )
3073 rtexture_t *dyntexture;
3074 // check whether its a dynamic texture
3075 // 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]
3076 dyntexture = CL_GetDynTexture( basename );
3077 item->base = dyntexture; // either NULL or dyntexture handle
3080 R_SkinFrame_MarkUsed(item);
3084 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3086 unsigned long long avgcolor[5], wsum; \
3094 for(pix = 0; pix < cnt; ++pix) \
3097 for(comp = 0; comp < 3; ++comp) \
3099 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3102 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3104 for(comp = 0; comp < 3; ++comp) \
3105 avgcolor[comp] += getpixel * w; \
3108 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3109 avgcolor[4] += getpixel; \
3111 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3113 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3114 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3115 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3116 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3119 extern cvar_t gl_picmip;
3120 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3123 unsigned char *pixels;
3124 unsigned char *bumppixels;
3125 unsigned char *basepixels = NULL;
3126 int basepixels_width = 0;
3127 int basepixels_height = 0;
3128 skinframe_t *skinframe;
3129 rtexture_t *ddsbase = NULL;
3130 qboolean ddshasalpha = false;
3131 float ddsavgcolor[4];
3132 char basename[MAX_QPATH];
3133 int miplevel = R_PicmipForFlags(textureflags);
3134 int savemiplevel = miplevel;
3137 if (cls.state == ca_dedicated)
3140 // return an existing skinframe if already loaded
3141 // if loading of the first image fails, don't make a new skinframe as it
3142 // would cause all future lookups of this to be missing
3143 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3144 if (skinframe && skinframe->base)
3147 Image_StripImageExtension(name, basename, sizeof(basename));
3149 // check for DDS texture file first
3150 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3152 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3153 if (basepixels == NULL)
3157 // FIXME handle miplevel
3159 if (developer_loading.integer)
3160 Con_Printf("loading skin \"%s\"\n", name);
3162 // we've got some pixels to store, so really allocate this new texture now
3164 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3165 skinframe->stain = NULL;
3166 skinframe->merged = NULL;
3167 skinframe->base = NULL;
3168 skinframe->pants = NULL;
3169 skinframe->shirt = NULL;
3170 skinframe->nmap = NULL;
3171 skinframe->gloss = NULL;
3172 skinframe->glow = NULL;
3173 skinframe->fog = NULL;
3174 skinframe->reflect = NULL;
3175 skinframe->hasalpha = false;
3179 skinframe->base = ddsbase;
3180 skinframe->hasalpha = ddshasalpha;
3181 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3182 if (r_loadfog && skinframe->hasalpha)
3183 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3184 //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]);
3188 basepixels_width = image_width;
3189 basepixels_height = image_height;
3190 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);
3191 if (textureflags & TEXF_ALPHA)
3193 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3195 if (basepixels[j] < 255)
3197 skinframe->hasalpha = true;
3201 if (r_loadfog && skinframe->hasalpha)
3203 // has transparent pixels
3204 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3205 for (j = 0;j < image_width * image_height * 4;j += 4)
3210 pixels[j+3] = basepixels[j+3];
3212 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);
3216 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3217 //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]);
3218 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3219 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3220 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3221 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3226 mymiplevel = savemiplevel;
3227 if (r_loadnormalmap)
3228 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);
3229 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3231 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3232 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3233 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3234 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3237 // _norm is the name used by tenebrae and has been adopted as standard
3238 if (r_loadnormalmap && skinframe->nmap == NULL)
3240 mymiplevel = savemiplevel;
3241 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3243 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);
3247 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3249 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3250 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3251 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3253 Mem_Free(bumppixels);
3255 else if (r_shadow_bumpscale_basetexture.value > 0)
3257 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3258 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3259 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 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3263 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3266 // _luma is supported only for tenebrae compatibility
3267 // _glow is the preferred name
3268 mymiplevel = savemiplevel;
3269 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
3271 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);
3272 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3273 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3274 Mem_Free(pixels);pixels = NULL;
3277 mymiplevel = savemiplevel;
3278 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3280 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);
3281 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3282 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3287 mymiplevel = savemiplevel;
3288 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3290 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);
3291 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3292 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3297 mymiplevel = savemiplevel;
3298 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3300 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);
3301 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3302 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3307 mymiplevel = savemiplevel;
3308 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3310 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);
3311 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3312 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3318 Mem_Free(basepixels);
3323 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3324 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3327 unsigned char *temp1, *temp2;
3328 skinframe_t *skinframe;
3330 if (cls.state == ca_dedicated)
3333 // if already loaded just return it, otherwise make a new skinframe
3334 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3335 if (skinframe && skinframe->base)
3338 skinframe->stain = NULL;
3339 skinframe->merged = NULL;
3340 skinframe->base = NULL;
3341 skinframe->pants = NULL;
3342 skinframe->shirt = NULL;
3343 skinframe->nmap = NULL;
3344 skinframe->gloss = NULL;
3345 skinframe->glow = NULL;
3346 skinframe->fog = NULL;
3347 skinframe->reflect = NULL;
3348 skinframe->hasalpha = false;
3350 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3354 if (developer_loading.integer)
3355 Con_Printf("loading 32bit skin \"%s\"\n", name);
3357 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3359 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3360 temp2 = temp1 + width * height * 4;
3361 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3362 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 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3366 if (textureflags & TEXF_ALPHA)
3368 for (i = 3;i < width * height * 4;i += 4)
3370 if (skindata[i] < 255)
3372 skinframe->hasalpha = true;
3376 if (r_loadfog && skinframe->hasalpha)
3378 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3379 memcpy(fogpixels, skindata, width * height * 4);
3380 for (i = 0;i < width * height * 4;i += 4)
3381 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3382 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3383 Mem_Free(fogpixels);
3387 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3388 //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]);
3393 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3397 skinframe_t *skinframe;
3399 if (cls.state == ca_dedicated)
3402 // if already loaded just return it, otherwise make a new skinframe
3403 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3404 if (skinframe && skinframe->base)
3407 skinframe->stain = NULL;
3408 skinframe->merged = NULL;
3409 skinframe->base = NULL;
3410 skinframe->pants = NULL;
3411 skinframe->shirt = NULL;
3412 skinframe->nmap = NULL;
3413 skinframe->gloss = NULL;
3414 skinframe->glow = NULL;
3415 skinframe->fog = NULL;
3416 skinframe->reflect = NULL;
3417 skinframe->hasalpha = false;
3419 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3423 if (developer_loading.integer)
3424 Con_Printf("loading quake skin \"%s\"\n", name);
3426 // 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)
3427 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3428 memcpy(skinframe->qpixels, skindata, width*height);
3429 skinframe->qwidth = width;
3430 skinframe->qheight = height;
3433 for (i = 0;i < width * height;i++)
3434 featuresmask |= palette_featureflags[skindata[i]];
3436 skinframe->hasalpha = false;
3437 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3438 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3439 skinframe->qgeneratemerged = true;
3440 skinframe->qgeneratebase = skinframe->qhascolormapping;
3441 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3443 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3444 //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]);
3449 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3453 unsigned char *skindata;
3455 if (!skinframe->qpixels)
3458 if (!skinframe->qhascolormapping)
3459 colormapped = false;
3463 if (!skinframe->qgeneratebase)
3468 if (!skinframe->qgeneratemerged)
3472 width = skinframe->qwidth;
3473 height = skinframe->qheight;
3474 skindata = skinframe->qpixels;
3476 if (skinframe->qgeneratenmap)
3478 unsigned char *temp1, *temp2;
3479 skinframe->qgeneratenmap = false;
3480 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3481 temp2 = temp1 + width * height * 4;
3482 // use either a custom palette or the quake palette
3483 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3484 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3485 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);
3489 if (skinframe->qgenerateglow)
3491 skinframe->qgenerateglow = false;
3492 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3497 skinframe->qgeneratebase = false;
3498 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);
3499 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3500 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3504 skinframe->qgeneratemerged = false;
3505 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 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3510 Mem_Free(skinframe->qpixels);
3511 skinframe->qpixels = NULL;
3515 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 skinframe_t *skinframe;
3520 if (cls.state == ca_dedicated)
3523 // if already loaded just return it, otherwise make a new skinframe
3524 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3525 if (skinframe && skinframe->base)
3528 skinframe->stain = NULL;
3529 skinframe->merged = NULL;
3530 skinframe->base = NULL;
3531 skinframe->pants = NULL;
3532 skinframe->shirt = NULL;
3533 skinframe->nmap = NULL;
3534 skinframe->gloss = NULL;
3535 skinframe->glow = NULL;
3536 skinframe->fog = NULL;
3537 skinframe->reflect = NULL;
3538 skinframe->hasalpha = false;
3540 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3544 if (developer_loading.integer)
3545 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3547 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3548 if (textureflags & TEXF_ALPHA)
3550 for (i = 0;i < width * height;i++)
3552 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3554 skinframe->hasalpha = true;
3558 if (r_loadfog && skinframe->hasalpha)
3559 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3562 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3563 //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]);
3568 skinframe_t *R_SkinFrame_LoadMissing(void)
3570 skinframe_t *skinframe;
3572 if (cls.state == ca_dedicated)
3575 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3576 skinframe->stain = NULL;
3577 skinframe->merged = NULL;
3578 skinframe->base = NULL;
3579 skinframe->pants = NULL;
3580 skinframe->shirt = NULL;
3581 skinframe->nmap = NULL;
3582 skinframe->gloss = NULL;
3583 skinframe->glow = NULL;
3584 skinframe->fog = NULL;
3585 skinframe->reflect = NULL;
3586 skinframe->hasalpha = false;
3588 skinframe->avgcolor[0] = rand() / RAND_MAX;
3589 skinframe->avgcolor[1] = rand() / RAND_MAX;
3590 skinframe->avgcolor[2] = rand() / RAND_MAX;
3591 skinframe->avgcolor[3] = 1;
3596 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3597 typedef struct suffixinfo_s
3600 qboolean flipx, flipy, flipdiagonal;
3603 static suffixinfo_t suffix[3][6] =
3606 {"px", false, false, false},
3607 {"nx", false, false, false},
3608 {"py", false, false, false},
3609 {"ny", false, false, false},
3610 {"pz", false, false, false},
3611 {"nz", false, false, false}
3614 {"posx", false, false, false},
3615 {"negx", false, false, false},
3616 {"posy", false, false, false},
3617 {"negy", false, false, false},
3618 {"posz", false, false, false},
3619 {"negz", false, false, false}
3622 {"rt", true, false, true},
3623 {"lf", false, true, true},
3624 {"ft", true, true, false},
3625 {"bk", false, false, false},
3626 {"up", true, false, true},
3627 {"dn", true, false, true}
3631 static int componentorder[4] = {0, 1, 2, 3};
3633 rtexture_t *R_LoadCubemap(const char *basename)
3635 int i, j, cubemapsize;
3636 unsigned char *cubemappixels, *image_buffer;
3637 rtexture_t *cubemaptexture;
3639 // must start 0 so the first loadimagepixels has no requested width/height
3641 cubemappixels = NULL;
3642 cubemaptexture = NULL;
3643 // keep trying different suffix groups (posx, px, rt) until one loads
3644 for (j = 0;j < 3 && !cubemappixels;j++)
3646 // load the 6 images in the suffix group
3647 for (i = 0;i < 6;i++)
3649 // generate an image name based on the base and and suffix
3650 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3652 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3654 // an image loaded, make sure width and height are equal
3655 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3657 // if this is the first image to load successfully, allocate the cubemap memory
3658 if (!cubemappixels && image_width >= 1)
3660 cubemapsize = image_width;
3661 // note this clears to black, so unavailable sides are black
3662 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3664 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3666 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 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3671 Mem_Free(image_buffer);
3675 // if a cubemap loaded, upload it
3678 if (developer_loading.integer)
3679 Con_Printf("loading cubemap \"%s\"\n", basename);
3681 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3682 Mem_Free(cubemappixels);
3686 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3687 if (developer_loading.integer)
3689 Con_Printf("(tried tried images ");
3690 for (j = 0;j < 3;j++)
3691 for (i = 0;i < 6;i++)
3692 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3693 Con_Print(" and was unable to find any of them).\n");
3696 return cubemaptexture;
3699 rtexture_t *R_GetCubemap(const char *basename)
3702 for (i = 0;i < r_texture_numcubemaps;i++)
3703 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3704 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3705 if (i >= MAX_CUBEMAPS)
3706 return r_texture_whitecube;
3707 r_texture_numcubemaps++;
3708 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3709 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3710 return r_texture_cubemaps[i].texture;
3713 void R_FreeCubemaps(void)
3716 for (i = 0;i < r_texture_numcubemaps;i++)
3718 if (developer_loading.integer)
3719 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3720 if (r_texture_cubemaps[i].texture)
3721 R_FreeTexture(r_texture_cubemaps[i].texture);
3723 r_texture_numcubemaps = 0;
3726 void R_Main_FreeViewCache(void)
3728 if (r_refdef.viewcache.entityvisible)
3729 Mem_Free(r_refdef.viewcache.entityvisible);
3730 if (r_refdef.viewcache.world_pvsbits)
3731 Mem_Free(r_refdef.viewcache.world_pvsbits);
3732 if (r_refdef.viewcache.world_leafvisible)
3733 Mem_Free(r_refdef.viewcache.world_leafvisible);
3734 if (r_refdef.viewcache.world_surfacevisible)
3735 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3736 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3739 void R_Main_ResizeViewCache(void)
3741 int numentities = r_refdef.scene.numentities;
3742 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3743 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3744 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3745 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3746 if (r_refdef.viewcache.maxentities < numentities)
3748 r_refdef.viewcache.maxentities = numentities;
3749 if (r_refdef.viewcache.entityvisible)
3750 Mem_Free(r_refdef.viewcache.entityvisible);
3751 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3753 if (r_refdef.viewcache.world_numclusters != numclusters)
3755 r_refdef.viewcache.world_numclusters = numclusters;
3756 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3757 if (r_refdef.viewcache.world_pvsbits)
3758 Mem_Free(r_refdef.viewcache.world_pvsbits);
3759 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3761 if (r_refdef.viewcache.world_numleafs != numleafs)
3763 r_refdef.viewcache.world_numleafs = numleafs;
3764 if (r_refdef.viewcache.world_leafvisible)
3765 Mem_Free(r_refdef.viewcache.world_leafvisible);
3766 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3768 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3770 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3771 if (r_refdef.viewcache.world_surfacevisible)
3772 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3773 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3777 extern rtexture_t *loadingscreentexture;
3778 void gl_main_start(void)
3780 loadingscreentexture = NULL;
3781 r_texture_blanknormalmap = NULL;
3782 r_texture_white = NULL;
3783 r_texture_grey128 = NULL;
3784 r_texture_black = NULL;
3785 r_texture_whitecube = NULL;
3786 r_texture_normalizationcube = NULL;
3787 r_texture_fogattenuation = NULL;
3788 r_texture_fogheighttexture = NULL;
3789 r_texture_gammaramps = NULL;
3790 r_texture_numcubemaps = 0;
3792 r_loaddds = r_texture_dds_load.integer != 0;
3793 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3795 switch(vid.renderpath)
3797 case RENDERPATH_GL20:
3798 case RENDERPATH_D3D9:
3799 case RENDERPATH_D3D10:
3800 case RENDERPATH_D3D11:
3801 case RENDERPATH_SOFT:
3802 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3803 Cvar_SetValueQuick(&gl_combine, 1);
3804 Cvar_SetValueQuick(&r_glsl, 1);
3805 r_loadnormalmap = true;
3809 case RENDERPATH_GL13:
3810 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3811 Cvar_SetValueQuick(&gl_combine, 1);
3812 Cvar_SetValueQuick(&r_glsl, 0);
3813 r_loadnormalmap = false;
3814 r_loadgloss = false;
3817 case RENDERPATH_GL11:
3818 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3819 Cvar_SetValueQuick(&gl_combine, 0);
3820 Cvar_SetValueQuick(&r_glsl, 0);
3821 r_loadnormalmap = false;
3822 r_loadgloss = false;
3825 case RENDERPATH_GLES2:
3826 Cvar_SetValueQuick(&r_textureunits, 1);
3827 Cvar_SetValueQuick(&gl_combine, 1);
3828 Cvar_SetValueQuick(&r_glsl, 1);
3829 r_loadnormalmap = true;
3830 r_loadgloss = false;
3836 R_FrameData_Reset();
3840 memset(r_queries, 0, sizeof(r_queries));
3842 r_qwskincache = NULL;
3843 r_qwskincache_size = 0;
3845 // set up r_skinframe loading system for textures
3846 memset(&r_skinframe, 0, sizeof(r_skinframe));
3847 r_skinframe.loadsequence = 1;
3848 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3850 r_main_texturepool = R_AllocTexturePool();
3851 R_BuildBlankTextures();
3853 if (vid.support.arb_texture_cube_map)
3856 R_BuildNormalizationCube();
3858 r_texture_fogattenuation = NULL;
3859 r_texture_fogheighttexture = NULL;
3860 r_texture_gammaramps = NULL;
3861 //r_texture_fogintensity = NULL;
3862 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3863 memset(&r_waterstate, 0, sizeof(r_waterstate));
3864 r_glsl_permutation = NULL;
3865 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3866 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3867 glslshaderstring = NULL;
3869 r_hlsl_permutation = NULL;
3870 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3871 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3873 hlslshaderstring = NULL;
3874 memset(&r_svbsp, 0, sizeof (r_svbsp));
3876 r_refdef.fogmasktable_density = 0;
3879 void gl_main_shutdown(void)
3882 R_FrameData_Reset();
3884 R_Main_FreeViewCache();
3886 switch(vid.renderpath)
3888 case RENDERPATH_GL11:
3889 case RENDERPATH_GL13:
3890 case RENDERPATH_GL20:
3891 case RENDERPATH_GLES2:
3893 qglDeleteQueriesARB(r_maxqueries, r_queries);
3895 case RENDERPATH_D3D9:
3896 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3898 case RENDERPATH_D3D10:
3899 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3901 case RENDERPATH_D3D11:
3902 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3904 case RENDERPATH_SOFT:
3910 memset(r_queries, 0, sizeof(r_queries));
3912 r_qwskincache = NULL;
3913 r_qwskincache_size = 0;
3915 // clear out the r_skinframe state
3916 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3917 memset(&r_skinframe, 0, sizeof(r_skinframe));
3920 Mem_Free(r_svbsp.nodes);
3921 memset(&r_svbsp, 0, sizeof (r_svbsp));
3922 R_FreeTexturePool(&r_main_texturepool);
3923 loadingscreentexture = NULL;
3924 r_texture_blanknormalmap = NULL;
3925 r_texture_white = NULL;
3926 r_texture_grey128 = NULL;
3927 r_texture_black = NULL;
3928 r_texture_whitecube = NULL;
3929 r_texture_normalizationcube = NULL;
3930 r_texture_fogattenuation = NULL;
3931 r_texture_fogheighttexture = NULL;
3932 r_texture_gammaramps = NULL;
3933 r_texture_numcubemaps = 0;
3934 //r_texture_fogintensity = NULL;
3935 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3936 memset(&r_waterstate, 0, sizeof(r_waterstate));
3939 r_glsl_permutation = NULL;
3940 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3941 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3942 glslshaderstring = NULL;
3944 r_hlsl_permutation = NULL;
3945 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3946 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3948 hlslshaderstring = NULL;
3951 extern void CL_ParseEntityLump(char *entitystring);
3952 void gl_main_newmap(void)
3954 // FIXME: move this code to client
3955 char *entities, entname[MAX_QPATH];
3957 Mem_Free(r_qwskincache);
3958 r_qwskincache = NULL;
3959 r_qwskincache_size = 0;
3962 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3963 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3965 CL_ParseEntityLump(entities);
3969 if (cl.worldmodel->brush.entities)
3970 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3972 R_Main_FreeViewCache();
3974 R_FrameData_Reset();
3977 void GL_Main_Init(void)
3979 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3981 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3982 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3983 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3984 if (gamemode == GAME_NEHAHRA)
3986 Cvar_RegisterVariable (&gl_fogenable);
3987 Cvar_RegisterVariable (&gl_fogdensity);
3988 Cvar_RegisterVariable (&gl_fogred);
3989 Cvar_RegisterVariable (&gl_foggreen);
3990 Cvar_RegisterVariable (&gl_fogblue);
3991 Cvar_RegisterVariable (&gl_fogstart);
3992 Cvar_RegisterVariable (&gl_fogend);
3993 Cvar_RegisterVariable (&gl_skyclip);
3995 Cvar_RegisterVariable(&r_motionblur);
3996 Cvar_RegisterVariable(&r_motionblur_maxblur);
3997 Cvar_RegisterVariable(&r_motionblur_bmin);
3998 Cvar_RegisterVariable(&r_motionblur_vmin);
3999 Cvar_RegisterVariable(&r_motionblur_vmax);
4000 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4001 Cvar_RegisterVariable(&r_motionblur_randomize);
4002 Cvar_RegisterVariable(&r_damageblur);
4003 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4004 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4005 Cvar_RegisterVariable(&r_equalize_entities_by);
4006 Cvar_RegisterVariable(&r_equalize_entities_to);
4007 Cvar_RegisterVariable(&r_depthfirst);
4008 Cvar_RegisterVariable(&r_useinfinitefarclip);
4009 Cvar_RegisterVariable(&r_farclip_base);
4010 Cvar_RegisterVariable(&r_farclip_world);
4011 Cvar_RegisterVariable(&r_nearclip);
4012 Cvar_RegisterVariable(&r_showbboxes);
4013 Cvar_RegisterVariable(&r_showsurfaces);
4014 Cvar_RegisterVariable(&r_showtris);
4015 Cvar_RegisterVariable(&r_shownormals);
4016 Cvar_RegisterVariable(&r_showlighting);
4017 Cvar_RegisterVariable(&r_showshadowvolumes);
4018 Cvar_RegisterVariable(&r_showcollisionbrushes);
4019 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4020 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4021 Cvar_RegisterVariable(&r_showdisabledepthtest);
4022 Cvar_RegisterVariable(&r_drawportals);
4023 Cvar_RegisterVariable(&r_drawentities);
4024 Cvar_RegisterVariable(&r_draw2d);
4025 Cvar_RegisterVariable(&r_drawworld);
4026 Cvar_RegisterVariable(&r_cullentities_trace);
4027 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4028 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4029 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4030 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4031 Cvar_RegisterVariable(&r_drawviewmodel);
4032 Cvar_RegisterVariable(&r_drawexteriormodel);
4033 Cvar_RegisterVariable(&r_speeds);
4034 Cvar_RegisterVariable(&r_fullbrights);
4035 Cvar_RegisterVariable(&r_wateralpha);
4036 Cvar_RegisterVariable(&r_dynamic);
4037 Cvar_RegisterVariable(&r_fakelight);
4038 Cvar_RegisterVariable(&r_fakelight_intensity);
4039 Cvar_RegisterVariable(&r_fullbright);
4040 Cvar_RegisterVariable(&r_shadows);
4041 Cvar_RegisterVariable(&r_shadows_darken);
4042 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4043 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4044 Cvar_RegisterVariable(&r_shadows_throwdistance);
4045 Cvar_RegisterVariable(&r_shadows_throwdirection);
4046 Cvar_RegisterVariable(&r_shadows_focus);
4047 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4048 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4049 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4050 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4051 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4052 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4053 Cvar_RegisterVariable(&r_fog_exp2);
4054 Cvar_RegisterVariable(&r_drawfog);
4055 Cvar_RegisterVariable(&r_transparentdepthmasking);
4056 Cvar_RegisterVariable(&r_texture_dds_load);
4057 Cvar_RegisterVariable(&r_texture_dds_save);
4058 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4059 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4060 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4061 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4062 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4063 Cvar_RegisterVariable(&r_textureunits);
4064 Cvar_RegisterVariable(&gl_combine);
4065 Cvar_RegisterVariable(&r_glsl);
4066 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4067 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4068 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4069 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4070 Cvar_RegisterVariable(&r_glsl_postprocess);
4071 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4072 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4073 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4074 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4075 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4076 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4077 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4078 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4080 Cvar_RegisterVariable(&r_water);
4081 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4082 Cvar_RegisterVariable(&r_water_clippingplanebias);
4083 Cvar_RegisterVariable(&r_water_refractdistort);
4084 Cvar_RegisterVariable(&r_water_reflectdistort);
4085 Cvar_RegisterVariable(&r_water_scissormode);
4086 Cvar_RegisterVariable(&r_lerpsprites);
4087 Cvar_RegisterVariable(&r_lerpmodels);
4088 Cvar_RegisterVariable(&r_lerplightstyles);
4089 Cvar_RegisterVariable(&r_waterscroll);
4090 Cvar_RegisterVariable(&r_bloom);
4091 Cvar_RegisterVariable(&r_bloom_colorscale);
4092 Cvar_RegisterVariable(&r_bloom_brighten);
4093 Cvar_RegisterVariable(&r_bloom_blur);
4094 Cvar_RegisterVariable(&r_bloom_resolution);
4095 Cvar_RegisterVariable(&r_bloom_colorexponent);
4096 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4097 Cvar_RegisterVariable(&r_hdr);
4098 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4099 Cvar_RegisterVariable(&r_hdr_glowintensity);
4100 Cvar_RegisterVariable(&r_hdr_range);
4101 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4102 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4103 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4104 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4105 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4106 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4107 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4108 Cvar_RegisterVariable(&developer_texturelogging);
4109 Cvar_RegisterVariable(&gl_lightmaps);
4110 Cvar_RegisterVariable(&r_test);
4111 Cvar_RegisterVariable(&r_glsl_saturation);
4112 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4113 Cvar_RegisterVariable(&r_framedatasize);
4114 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4115 Cvar_SetValue("r_fullbrights", 0);
4116 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4118 Cvar_RegisterVariable(&r_track_sprites);
4119 Cvar_RegisterVariable(&r_track_sprites_flags);
4120 Cvar_RegisterVariable(&r_track_sprites_scalew);
4121 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4122 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4123 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4124 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4125 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4128 extern void R_Textures_Init(void);
4129 extern void GL_Draw_Init(void);
4130 extern void GL_Main_Init(void);
4131 extern void R_Shadow_Init(void);
4132 extern void R_Sky_Init(void);
4133 extern void GL_Surf_Init(void);
4134 extern void R_Particles_Init(void);
4135 extern void R_Explosion_Init(void);
4136 extern void gl_backend_init(void);
4137 extern void Sbar_Init(void);
4138 extern void R_LightningBeams_Init(void);
4139 extern void Mod_RenderInit(void);
4140 extern void Font_Init(void);
4142 void Render_Init(void)
4155 R_LightningBeams_Init();
4164 extern char *ENGINE_EXTENSIONS;
4167 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4168 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4169 gl_version = (const char *)qglGetString(GL_VERSION);
4170 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4174 if (!gl_platformextensions)
4175 gl_platformextensions = "";
4177 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4178 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4179 Con_Printf("GL_VERSION: %s\n", gl_version);
4180 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4181 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4183 VID_CheckExtensions();
4185 // LordHavoc: report supported extensions
4186 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4188 // clear to black (loading plaque will be seen over this)
4189 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4192 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4196 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4198 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4201 p = r_refdef.view.frustum + i;
4206 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4210 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4214 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4218 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4222 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4226 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4230 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4234 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4242 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4246 for (i = 0;i < numplanes;i++)
4253 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4257 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4261 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4265 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4269 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4273 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4277 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4281 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4289 //==================================================================================
4291 // LordHavoc: this stores temporary data used within the same frame
4293 typedef struct r_framedata_mem_s
4295 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4296 size_t size; // how much usable space
4297 size_t current; // how much space in use
4298 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4299 size_t wantedsize; // how much space was allocated
4300 unsigned char *data; // start of real data (16byte aligned)
4304 static r_framedata_mem_t *r_framedata_mem;
4306 void R_FrameData_Reset(void)
4308 while (r_framedata_mem)
4310 r_framedata_mem_t *next = r_framedata_mem->purge;
4311 Mem_Free(r_framedata_mem);
4312 r_framedata_mem = next;
4316 void R_FrameData_Resize(void)
4319 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4320 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4321 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4323 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4324 newmem->wantedsize = wantedsize;
4325 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4326 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4327 newmem->current = 0;
4329 newmem->purge = r_framedata_mem;
4330 r_framedata_mem = newmem;
4334 void R_FrameData_NewFrame(void)
4336 R_FrameData_Resize();
4337 if (!r_framedata_mem)
4339 // if we ran out of space on the last frame, free the old memory now
4340 while (r_framedata_mem->purge)
4342 // repeatedly remove the second item in the list, leaving only head
4343 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4344 Mem_Free(r_framedata_mem->purge);
4345 r_framedata_mem->purge = next;
4347 // reset the current mem pointer
4348 r_framedata_mem->current = 0;
4349 r_framedata_mem->mark = 0;
4352 void *R_FrameData_Alloc(size_t size)
4356 // align to 16 byte boundary - the data pointer is already aligned, so we
4357 // only need to ensure the size of every allocation is also aligned
4358 size = (size + 15) & ~15;
4360 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4362 // emergency - we ran out of space, allocate more memory
4363 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4364 R_FrameData_Resize();
4367 data = r_framedata_mem->data + r_framedata_mem->current;
4368 r_framedata_mem->current += size;
4370 // count the usage for stats
4371 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4372 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4374 return (void *)data;
4377 void *R_FrameData_Store(size_t size, void *data)
4379 void *d = R_FrameData_Alloc(size);
4381 memcpy(d, data, size);
4385 void R_FrameData_SetMark(void)
4387 if (!r_framedata_mem)
4389 r_framedata_mem->mark = r_framedata_mem->current;
4392 void R_FrameData_ReturnToMark(void)
4394 if (!r_framedata_mem)
4396 r_framedata_mem->current = r_framedata_mem->mark;
4399 //==================================================================================
4401 // LordHavoc: animcache originally written by Echon, rewritten since then
4404 * Animation cache prevents re-generating mesh data for an animated model
4405 * multiple times in one frame for lighting, shadowing, reflections, etc.
4408 void R_AnimCache_Free(void)
4412 void R_AnimCache_ClearCache(void)
4415 entity_render_t *ent;
4417 for (i = 0;i < r_refdef.scene.numentities;i++)
4419 ent = r_refdef.scene.entities[i];
4420 ent->animcache_vertex3f = NULL;
4421 ent->animcache_normal3f = NULL;
4422 ent->animcache_svector3f = NULL;
4423 ent->animcache_tvector3f = NULL;
4424 ent->animcache_vertexmesh = NULL;
4425 ent->animcache_vertex3fbuffer = NULL;
4426 ent->animcache_vertexmeshbuffer = NULL;
4430 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4434 // check if we need the meshbuffers
4435 if (!vid.useinterleavedarrays)
4438 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4439 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4440 // TODO: upload vertex3f buffer?
4441 if (ent->animcache_vertexmesh)
4443 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4444 for (i = 0;i < numvertices;i++)
4445 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4446 if (ent->animcache_svector3f)
4447 for (i = 0;i < numvertices;i++)
4448 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4449 if (ent->animcache_tvector3f)
4450 for (i = 0;i < numvertices;i++)
4451 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4452 if (ent->animcache_normal3f)
4453 for (i = 0;i < numvertices;i++)
4454 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4455 // TODO: upload vertexmeshbuffer?
4459 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4461 dp_model_t *model = ent->model;
4463 // see if it's already cached this frame
4464 if (ent->animcache_vertex3f)
4466 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4467 if (wantnormals || wanttangents)
4469 if (ent->animcache_normal3f)
4470 wantnormals = false;
4471 if (ent->animcache_svector3f)
4472 wanttangents = false;
4473 if (wantnormals || wanttangents)
4475 numvertices = model->surfmesh.num_vertices;
4477 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4480 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4481 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4483 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4484 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4490 // see if this ent is worth caching
4491 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4493 // get some memory for this entity and generate mesh data
4494 numvertices = model->surfmesh.num_vertices;
4495 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4497 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4500 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4501 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4503 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4504 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4509 void R_AnimCache_CacheVisibleEntities(void)
4512 qboolean wantnormals = true;
4513 qboolean wanttangents = !r_showsurfaces.integer;
4515 switch(vid.renderpath)
4517 case RENDERPATH_GL20:
4518 case RENDERPATH_D3D9:
4519 case RENDERPATH_D3D10:
4520 case RENDERPATH_D3D11:
4521 case RENDERPATH_GLES2:
4523 case RENDERPATH_GL13:
4524 case RENDERPATH_GL11:
4525 wanttangents = false;
4527 case RENDERPATH_SOFT:
4531 if (r_shownormals.integer)
4532 wanttangents = wantnormals = true;
4534 // TODO: thread this
4535 // NOTE: R_PrepareRTLights() also caches entities
4537 for (i = 0;i < r_refdef.scene.numentities;i++)
4538 if (r_refdef.viewcache.entityvisible[i])
4539 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4542 //==================================================================================
4544 static void R_View_UpdateEntityLighting (void)
4547 entity_render_t *ent;
4548 vec3_t tempdiffusenormal, avg;
4549 vec_t f, fa, fd, fdd;
4550 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4552 for (i = 0;i < r_refdef.scene.numentities;i++)
4554 ent = r_refdef.scene.entities[i];
4556 // skip unseen models
4557 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4561 if (ent->model && ent->model->brush.num_leafs)
4563 // TODO: use modellight for r_ambient settings on world?
4564 VectorSet(ent->modellight_ambient, 0, 0, 0);
4565 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4566 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4570 // fetch the lighting from the worldmodel data
4571 VectorClear(ent->modellight_ambient);
4572 VectorClear(ent->modellight_diffuse);
4573 VectorClear(tempdiffusenormal);
4574 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4577 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4579 // complete lightning for lit sprites
4580 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4581 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4583 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4584 org[2] = org[2] + r_overheadsprites_pushback.value;
4585 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4588 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4590 if(ent->flags & RENDER_EQUALIZE)
4592 // first fix up ambient lighting...
4593 if(r_equalize_entities_minambient.value > 0)
4595 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4598 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4599 if(fa < r_equalize_entities_minambient.value * fd)
4602 // fa'/fd' = minambient
4603 // fa'+0.25*fd' = fa+0.25*fd
4605 // fa' = fd' * minambient
4606 // fd'*(0.25+minambient) = fa+0.25*fd
4608 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4609 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4611 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4612 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
4613 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4614 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4619 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4621 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4622 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4626 // adjust brightness and saturation to target
4627 avg[0] = avg[1] = avg[2] = fa / f;
4628 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4629 avg[0] = avg[1] = avg[2] = fd / f;
4630 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4636 VectorSet(ent->modellight_ambient, 1, 1, 1);
4638 // move the light direction into modelspace coordinates for lighting code
4639 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4640 if(VectorLength2(ent->modellight_lightdir) == 0)
4641 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4642 VectorNormalize(ent->modellight_lightdir);
4646 #define MAX_LINEOFSIGHTTRACES 64
4648 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4651 vec3_t boxmins, boxmaxs;
4654 dp_model_t *model = r_refdef.scene.worldmodel;
4656 if (!model || !model->brush.TraceLineOfSight)
4659 // expand the box a little
4660 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4661 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4662 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4663 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4664 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4665 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4667 // return true if eye is inside enlarged box
4668 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4672 VectorCopy(eye, start);
4673 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4674 if (model->brush.TraceLineOfSight(model, start, end))
4677 // try various random positions
4678 for (i = 0;i < numsamples;i++)
4680 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4681 if (model->brush.TraceLineOfSight(model, start, end))
4689 static void R_View_UpdateEntityVisible (void)
4694 entity_render_t *ent;
4696 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4697 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4698 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4699 : RENDER_EXTERIORMODEL;
4700 if (!r_drawviewmodel.integer)
4701 renderimask |= RENDER_VIEWMODEL;
4702 if (!r_drawexteriormodel.integer)
4703 renderimask |= RENDER_EXTERIORMODEL;
4704 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4706 // worldmodel can check visibility
4707 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4708 for (i = 0;i < r_refdef.scene.numentities;i++)
4710 ent = r_refdef.scene.entities[i];
4711 if (!(ent->flags & renderimask))
4712 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)))
4713 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))
4714 r_refdef.viewcache.entityvisible[i] = true;
4716 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4717 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4719 for (i = 0;i < r_refdef.scene.numentities;i++)
4721 ent = r_refdef.scene.entities[i];
4722 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4724 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4726 continue; // temp entities do pvs only
4727 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4728 ent->last_trace_visibility = realtime;
4729 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4730 r_refdef.viewcache.entityvisible[i] = 0;
4737 // no worldmodel or it can't check visibility
4738 for (i = 0;i < r_refdef.scene.numentities;i++)
4740 ent = r_refdef.scene.entities[i];
4741 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 /// only used if skyrendermasked, and normally returns false
4747 int R_DrawBrushModelsSky (void)
4750 entity_render_t *ent;
4753 for (i = 0;i < r_refdef.scene.numentities;i++)
4755 if (!r_refdef.viewcache.entityvisible[i])
4757 ent = r_refdef.scene.entities[i];
4758 if (!ent->model || !ent->model->DrawSky)
4760 ent->model->DrawSky(ent);
4766 static void R_DrawNoModel(entity_render_t *ent);
4767 static void R_DrawModels(void)
4770 entity_render_t *ent;
4772 for (i = 0;i < r_refdef.scene.numentities;i++)
4774 if (!r_refdef.viewcache.entityvisible[i])
4776 ent = r_refdef.scene.entities[i];
4777 r_refdef.stats.entities++;
4778 if (ent->model && ent->model->Draw != NULL)
4779 ent->model->Draw(ent);
4785 static void R_DrawModelsDepth(void)
4788 entity_render_t *ent;
4790 for (i = 0;i < r_refdef.scene.numentities;i++)
4792 if (!r_refdef.viewcache.entityvisible[i])
4794 ent = r_refdef.scene.entities[i];
4795 if (ent->model && ent->model->DrawDepth != NULL)
4796 ent->model->DrawDepth(ent);
4800 static void R_DrawModelsDebug(void)
4803 entity_render_t *ent;
4805 for (i = 0;i < r_refdef.scene.numentities;i++)
4807 if (!r_refdef.viewcache.entityvisible[i])
4809 ent = r_refdef.scene.entities[i];
4810 if (ent->model && ent->model->DrawDebug != NULL)
4811 ent->model->DrawDebug(ent);
4815 static void R_DrawModelsAddWaterPlanes(void)
4818 entity_render_t *ent;
4820 for (i = 0;i < r_refdef.scene.numentities;i++)
4822 if (!r_refdef.viewcache.entityvisible[i])
4824 ent = r_refdef.scene.entities[i];
4825 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4826 ent->model->DrawAddWaterPlanes(ent);
4830 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4832 if (r_hdr_irisadaptation.integer)
4836 vec3_t diffusenormal;
4841 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4842 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4843 brightness = max(0.0000001f, brightness);
4844 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4845 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4846 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4847 current = r_hdr_irisadaptation_value.value;
4849 current = min(current + adjust, goal);
4850 else if (current > goal)
4851 current = max(current - adjust, goal);
4852 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4853 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4855 else if (r_hdr_irisadaptation_value.value != 1.0f)
4856 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4859 static void R_View_SetFrustum(const int *scissor)
4862 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4863 vec3_t forward, left, up, origin, v;
4867 // flipped x coordinates (because x points left here)
4868 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4869 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4871 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4872 switch(vid.renderpath)
4874 case RENDERPATH_D3D9:
4875 case RENDERPATH_D3D10:
4876 case RENDERPATH_D3D11:
4877 case RENDERPATH_SOFT:
4878 // non-flipped y coordinates
4879 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4880 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4882 case RENDERPATH_GL11:
4883 case RENDERPATH_GL13:
4884 case RENDERPATH_GL20:
4885 case RENDERPATH_GLES2:
4886 // non-flipped y coordinates
4887 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4888 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4893 // we can't trust r_refdef.view.forward and friends in reflected scenes
4894 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4897 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4898 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4899 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4900 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4901 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4902 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4903 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4904 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4905 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4906 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4907 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4908 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4912 zNear = r_refdef.nearclip;
4913 nudge = 1.0 - 1.0 / (1<<23);
4914 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4915 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4916 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4917 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4918 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4919 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4920 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4921 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4927 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4928 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4929 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4930 r_refdef.view.frustum[0].dist = m[15] - m[12];
4932 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4933 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4934 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4935 r_refdef.view.frustum[1].dist = m[15] + m[12];
4937 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4938 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4939 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4940 r_refdef.view.frustum[2].dist = m[15] - m[13];
4942 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4943 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4944 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4945 r_refdef.view.frustum[3].dist = m[15] + m[13];
4947 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4948 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4949 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4950 r_refdef.view.frustum[4].dist = m[15] - m[14];
4952 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4953 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4954 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4955 r_refdef.view.frustum[5].dist = m[15] + m[14];
4958 if (r_refdef.view.useperspective)
4960 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4961 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]);
4962 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]);
4963 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]);
4964 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
4966 // then the normals from the corners relative to origin
4967 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4968 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4969 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4970 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4972 // in a NORMAL view, forward cross left == up
4973 // in a REFLECTED view, forward cross left == down
4974 // so our cross products above need to be adjusted for a left handed coordinate system
4975 CrossProduct(forward, left, v);
4976 if(DotProduct(v, up) < 0)
4978 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4979 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
4980 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
4981 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
4984 // Leaving those out was a mistake, those were in the old code, and they
4985 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4986 // I couldn't reproduce it after adding those normalizations. --blub
4987 VectorNormalize(r_refdef.view.frustum[0].normal);
4988 VectorNormalize(r_refdef.view.frustum[1].normal);
4989 VectorNormalize(r_refdef.view.frustum[2].normal);
4990 VectorNormalize(r_refdef.view.frustum[3].normal);
4992 // make the corners absolute
4993 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
4994 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
4995 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
4996 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
4999 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5001 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5002 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5003 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5004 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5005 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5009 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5010 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5011 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5012 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5013 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5014 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5015 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5016 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5017 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5018 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5020 r_refdef.view.numfrustumplanes = 5;
5022 if (r_refdef.view.useclipplane)
5024 r_refdef.view.numfrustumplanes = 6;
5025 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5028 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5029 PlaneClassify(r_refdef.view.frustum + i);
5031 // LordHavoc: note to all quake engine coders, Quake had a special case
5032 // for 90 degrees which assumed a square view (wrong), so I removed it,
5033 // Quake2 has it disabled as well.
5035 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5036 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5037 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5038 //PlaneClassify(&frustum[0]);
5040 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5041 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5042 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5043 //PlaneClassify(&frustum[1]);
5045 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5046 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5047 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5048 //PlaneClassify(&frustum[2]);
5050 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5051 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5052 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5053 //PlaneClassify(&frustum[3]);
5056 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5057 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5058 //PlaneClassify(&frustum[4]);
5061 void R_View_UpdateWithScissor(const int *myscissor)
5063 R_Main_ResizeViewCache();
5064 R_View_SetFrustum(myscissor);
5065 R_View_WorldVisibility(r_refdef.view.useclipplane);
5066 R_View_UpdateEntityVisible();
5067 R_View_UpdateEntityLighting();
5070 void R_View_Update(void)
5072 R_Main_ResizeViewCache();
5073 R_View_SetFrustum(NULL);
5074 R_View_WorldVisibility(r_refdef.view.useclipplane);
5075 R_View_UpdateEntityVisible();
5076 R_View_UpdateEntityLighting();
5079 void R_SetupView(qboolean allowwaterclippingplane)
5081 const float *customclipplane = NULL;
5083 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5085 // LordHavoc: couldn't figure out how to make this approach the
5086 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5087 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5088 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5089 dist = r_refdef.view.clipplane.dist;
5090 plane[0] = r_refdef.view.clipplane.normal[0];
5091 plane[1] = r_refdef.view.clipplane.normal[1];
5092 plane[2] = r_refdef.view.clipplane.normal[2];
5094 customclipplane = plane;
5097 if (!r_refdef.view.useperspective)
5098 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);
5099 else if (vid.stencil && r_useinfinitefarclip.integer)
5100 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5102 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);
5103 R_SetViewport(&r_refdef.view.viewport);
5106 void R_EntityMatrix(const matrix4x4_t *matrix)
5108 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5110 gl_modelmatrixchanged = false;
5111 gl_modelmatrix = *matrix;
5112 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5113 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5114 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5115 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5117 switch(vid.renderpath)
5119 case RENDERPATH_D3D9:
5121 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5122 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5125 case RENDERPATH_D3D10:
5126 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5128 case RENDERPATH_D3D11:
5129 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5131 case RENDERPATH_GL13:
5132 case RENDERPATH_GL11:
5133 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5135 case RENDERPATH_SOFT:
5136 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5137 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5139 case RENDERPATH_GL20:
5140 case RENDERPATH_GLES2:
5141 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5142 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5148 void R_ResetViewRendering2D(void)
5150 r_viewport_t viewport;
5153 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5154 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);
5155 R_SetViewport(&viewport);
5156 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5157 GL_Color(1, 1, 1, 1);
5158 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5159 GL_BlendFunc(GL_ONE, GL_ZERO);
5160 GL_ScissorTest(false);
5161 GL_DepthMask(false);
5162 GL_DepthRange(0, 1);
5163 GL_DepthTest(false);
5164 GL_DepthFunc(GL_LEQUAL);
5165 R_EntityMatrix(&identitymatrix);
5166 R_Mesh_ResetTextureState();
5167 GL_PolygonOffset(0, 0);
5168 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5169 switch(vid.renderpath)
5171 case RENDERPATH_GL11:
5172 case RENDERPATH_GL13:
5173 case RENDERPATH_GL20:
5174 case RENDERPATH_GLES2:
5175 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5177 case RENDERPATH_D3D9:
5178 case RENDERPATH_D3D10:
5179 case RENDERPATH_D3D11:
5180 case RENDERPATH_SOFT:
5183 GL_CullFace(GL_NONE);
5186 void R_ResetViewRendering3D(void)
5191 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5192 GL_Color(1, 1, 1, 1);
5193 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5194 GL_BlendFunc(GL_ONE, GL_ZERO);
5195 GL_ScissorTest(true);
5197 GL_DepthRange(0, 1);
5199 GL_DepthFunc(GL_LEQUAL);
5200 R_EntityMatrix(&identitymatrix);
5201 R_Mesh_ResetTextureState();
5202 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5203 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5204 switch(vid.renderpath)
5206 case RENDERPATH_GL11:
5207 case RENDERPATH_GL13:
5208 case RENDERPATH_GL20:
5209 case RENDERPATH_GLES2:
5210 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5212 case RENDERPATH_D3D9:
5213 case RENDERPATH_D3D10:
5214 case RENDERPATH_D3D11:
5215 case RENDERPATH_SOFT:
5218 GL_CullFace(r_refdef.view.cullface_back);
5223 R_RenderView_UpdateViewVectors
5226 static void R_RenderView_UpdateViewVectors(void)
5228 // break apart the view matrix into vectors for various purposes
5229 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5230 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5231 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5232 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5233 // make an inverted copy of the view matrix for tracking sprites
5234 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5237 void R_RenderScene(void);
5238 void R_RenderWaterPlanes(void);
5240 static void R_Water_StartFrame(void)
5243 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5244 r_waterstate_waterplane_t *p;
5246 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5249 switch(vid.renderpath)
5251 case RENDERPATH_GL20:
5252 case RENDERPATH_D3D9:
5253 case RENDERPATH_D3D10:
5254 case RENDERPATH_D3D11:
5255 case RENDERPATH_SOFT:
5256 case RENDERPATH_GLES2:
5258 case RENDERPATH_GL13:
5259 case RENDERPATH_GL11:
5263 // set waterwidth and waterheight to the water resolution that will be
5264 // used (often less than the screen resolution for faster rendering)
5265 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5266 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5268 // calculate desired texture sizes
5269 // can't use water if the card does not support the texture size
5270 if (!r_water.integer || r_showsurfaces.integer)
5271 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5272 else if (vid.support.arb_texture_non_power_of_two)
5274 texturewidth = waterwidth;
5275 textureheight = waterheight;
5276 camerawidth = waterwidth;
5277 cameraheight = waterheight;
5281 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5282 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5283 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5284 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5287 // allocate textures as needed
5288 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5290 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5291 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5293 if (p->texture_refraction)
5294 R_FreeTexture(p->texture_refraction);
5295 p->texture_refraction = NULL;
5296 if (p->texture_reflection)
5297 R_FreeTexture(p->texture_reflection);
5298 p->texture_reflection = NULL;
5299 if (p->texture_camera)
5300 R_FreeTexture(p->texture_camera);
5301 p->texture_camera = NULL;
5303 memset(&r_waterstate, 0, sizeof(r_waterstate));
5304 r_waterstate.texturewidth = texturewidth;
5305 r_waterstate.textureheight = textureheight;
5306 r_waterstate.camerawidth = camerawidth;
5307 r_waterstate.cameraheight = cameraheight;
5310 if (r_waterstate.texturewidth)
5312 r_waterstate.enabled = true;
5314 // when doing a reduced render (HDR) we want to use a smaller area
5315 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5316 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5318 // set up variables that will be used in shader setup
5319 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5320 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5321 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5322 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5325 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5326 r_waterstate.numwaterplanes = 0;
5329 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5331 int triangleindex, planeindex;
5337 r_waterstate_waterplane_t *p;
5338 texture_t *t = R_GetCurrentTexture(surface->texture);
5340 // just use the first triangle with a valid normal for any decisions
5341 VectorClear(normal);
5342 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5344 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5345 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5346 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5347 TriangleNormal(vert[0], vert[1], vert[2], normal);
5348 if (VectorLength2(normal) >= 0.001)
5352 VectorCopy(normal, plane.normal);
5353 VectorNormalize(plane.normal);
5354 plane.dist = DotProduct(vert[0], plane.normal);
5355 PlaneClassify(&plane);
5356 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5358 // skip backfaces (except if nocullface is set)
5359 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5361 VectorNegate(plane.normal, plane.normal);
5363 PlaneClassify(&plane);
5367 // find a matching plane if there is one
5368 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5369 if(p->camera_entity == t->camera_entity)
5370 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5372 if (planeindex >= r_waterstate.maxwaterplanes)
5373 return; // nothing we can do, out of planes
5375 // if this triangle does not fit any known plane rendered this frame, add one
5376 if (planeindex >= r_waterstate.numwaterplanes)
5378 // store the new plane
5379 r_waterstate.numwaterplanes++;
5381 // clear materialflags and pvs
5382 p->materialflags = 0;
5383 p->pvsvalid = false;
5384 p->camera_entity = t->camera_entity;
5385 VectorCopy(surface->mins, p->mins);
5386 VectorCopy(surface->maxs, p->maxs);
5391 p->mins[0] = min(p->mins[0], surface->mins[0]);
5392 p->mins[1] = min(p->mins[1], surface->mins[1]);
5393 p->mins[2] = min(p->mins[2], surface->mins[2]);
5394 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5395 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5396 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5398 // merge this surface's materialflags into the waterplane
5399 p->materialflags |= t->currentmaterialflags;
5400 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5402 // merge this surface's PVS into the waterplane
5403 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5404 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5405 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5407 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5413 static void R_Water_ProcessPlanes(void)
5416 r_refdef_view_t originalview;
5417 r_refdef_view_t myview;
5419 r_waterstate_waterplane_t *p;
5422 originalview = r_refdef.view;
5424 // make sure enough textures are allocated
5425 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5427 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5429 if (!p->texture_refraction)
5430 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);
5431 if (!p->texture_refraction)
5434 else if (p->materialflags & MATERIALFLAG_CAMERA)
5436 if (!p->texture_camera)
5437 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);
5438 if (!p->texture_camera)
5442 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5444 if (!p->texture_reflection)
5445 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);
5446 if (!p->texture_reflection)
5452 r_refdef.view = originalview;
5453 r_refdef.view.showdebug = false;
5454 r_refdef.view.width = r_waterstate.waterwidth;
5455 r_refdef.view.height = r_waterstate.waterheight;
5456 r_refdef.view.useclipplane = true;
5457 myview = r_refdef.view;
5458 r_waterstate.renderingscene = true;
5459 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5461 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5463 r_refdef.view = myview;
5464 if(r_water_scissormode.integer)
5467 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5468 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5471 // render reflected scene and copy into texture
5472 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5473 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5474 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5475 r_refdef.view.clipplane = p->plane;
5477 // reverse the cullface settings for this render
5478 r_refdef.view.cullface_front = GL_FRONT;
5479 r_refdef.view.cullface_back = GL_BACK;
5480 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5482 r_refdef.view.usecustompvs = true;
5484 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5486 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5489 R_ResetViewRendering3D();
5490 R_ClearScreen(r_refdef.fogenabled);
5491 if(r_water_scissormode.integer & 2)
5492 R_View_UpdateWithScissor(myscissor);
5495 if(r_water_scissormode.integer & 1)
5496 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5499 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);
5502 // render the normal view scene and copy into texture
5503 // (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)
5504 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5506 r_refdef.view = myview;
5507 if(r_water_scissormode.integer)
5510 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5511 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5514 r_waterstate.renderingrefraction = true;
5516 r_refdef.view.clipplane = p->plane;
5517 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5518 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5520 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5522 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5523 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5524 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5525 R_RenderView_UpdateViewVectors();
5526 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5528 r_refdef.view.usecustompvs = true;
5529 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);
5533 PlaneClassify(&r_refdef.view.clipplane);
5535 R_ResetViewRendering3D();
5536 R_ClearScreen(r_refdef.fogenabled);
5537 if(r_water_scissormode.integer & 2)
5538 R_View_UpdateWithScissor(myscissor);
5541 if(r_water_scissormode.integer & 1)
5542 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5545 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);
5546 r_waterstate.renderingrefraction = false;
5548 else if (p->materialflags & MATERIALFLAG_CAMERA)
5550 r_refdef.view = myview;
5552 r_refdef.view.clipplane = p->plane;
5553 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5554 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5556 r_refdef.view.width = r_waterstate.camerawidth;
5557 r_refdef.view.height = r_waterstate.cameraheight;
5558 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5559 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5561 if(p->camera_entity)
5563 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5564 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5567 // note: all of the view is used for displaying... so
5568 // there is no use in scissoring
5570 // reverse the cullface settings for this render
5571 r_refdef.view.cullface_front = GL_FRONT;
5572 r_refdef.view.cullface_back = GL_BACK;
5573 // also reverse the view matrix
5574 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
5575 R_RenderView_UpdateViewVectors();
5576 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5578 r_refdef.view.usecustompvs = true;
5579 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);
5582 // camera needs no clipplane
5583 r_refdef.view.useclipplane = false;
5585 PlaneClassify(&r_refdef.view.clipplane);
5587 R_ResetViewRendering3D();
5588 R_ClearScreen(r_refdef.fogenabled);
5592 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);
5593 r_waterstate.renderingrefraction = false;
5597 r_waterstate.renderingscene = false;
5598 r_refdef.view = originalview;
5599 R_ResetViewRendering3D();
5600 R_ClearScreen(r_refdef.fogenabled);
5604 r_refdef.view = originalview;
5605 r_waterstate.renderingscene = false;
5606 Cvar_SetValueQuick(&r_water, 0);
5607 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5611 void R_Bloom_StartFrame(void)
5613 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5615 switch(vid.renderpath)
5617 case RENDERPATH_GL20:
5618 case RENDERPATH_D3D9:
5619 case RENDERPATH_D3D10:
5620 case RENDERPATH_D3D11:
5621 case RENDERPATH_SOFT:
5622 case RENDERPATH_GLES2:
5624 case RENDERPATH_GL13:
5625 case RENDERPATH_GL11:
5629 // set bloomwidth and bloomheight to the bloom resolution that will be
5630 // used (often less than the screen resolution for faster rendering)
5631 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5632 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5633 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5634 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5635 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5637 // calculate desired texture sizes
5638 if (vid.support.arb_texture_non_power_of_two)
5640 screentexturewidth = r_refdef.view.width;
5641 screentextureheight = r_refdef.view.height;
5642 bloomtexturewidth = r_bloomstate.bloomwidth;
5643 bloomtextureheight = r_bloomstate.bloomheight;
5647 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5648 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5649 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5650 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5653 if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
5655 Cvar_SetValueQuick(&r_hdr, 0);
5656 Cvar_SetValueQuick(&r_bloom, 0);
5657 Cvar_SetValueQuick(&r_motionblur, 0);
5658 Cvar_SetValueQuick(&r_damageblur, 0);
5661 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)))
5662 screentexturewidth = screentextureheight = 0;
5663 if (!r_hdr.integer && !r_bloom.integer)
5664 bloomtexturewidth = bloomtextureheight = 0;
5666 // allocate textures as needed
5667 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5669 if (r_bloomstate.texture_screen)
5670 R_FreeTexture(r_bloomstate.texture_screen);
5671 r_bloomstate.texture_screen = NULL;
5672 r_bloomstate.screentexturewidth = screentexturewidth;
5673 r_bloomstate.screentextureheight = screentextureheight;
5674 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5675 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
5677 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5679 if (r_bloomstate.texture_bloom)
5680 R_FreeTexture(r_bloomstate.texture_bloom);
5681 r_bloomstate.texture_bloom = NULL;
5682 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5683 r_bloomstate.bloomtextureheight = bloomtextureheight;
5684 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5685 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);
5688 // when doing a reduced render (HDR) we want to use a smaller area
5689 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5690 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5691 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5692 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5693 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5695 // set up a texcoord array for the full resolution screen image
5696 // (we have to keep this around to copy back during final render)
5697 r_bloomstate.screentexcoord2f[0] = 0;
5698 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5699 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5700 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5701 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5702 r_bloomstate.screentexcoord2f[5] = 0;
5703 r_bloomstate.screentexcoord2f[6] = 0;
5704 r_bloomstate.screentexcoord2f[7] = 0;
5706 // set up a texcoord array for the reduced resolution bloom image
5707 // (which will be additive blended over the screen image)
5708 r_bloomstate.bloomtexcoord2f[0] = 0;
5709 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5710 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5711 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5712 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5713 r_bloomstate.bloomtexcoord2f[5] = 0;
5714 r_bloomstate.bloomtexcoord2f[6] = 0;
5715 r_bloomstate.bloomtexcoord2f[7] = 0;
5717 switch(vid.renderpath)
5719 case RENDERPATH_GL11:
5720 case RENDERPATH_GL13:
5721 case RENDERPATH_GL20:
5722 case RENDERPATH_SOFT:
5723 case RENDERPATH_GLES2:
5725 case RENDERPATH_D3D9:
5726 case RENDERPATH_D3D10:
5727 case RENDERPATH_D3D11:
5730 for (i = 0;i < 4;i++)
5732 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5733 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5734 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5735 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5741 if (r_hdr.integer || r_bloom.integer)
5743 r_bloomstate.enabled = true;
5744 r_bloomstate.hdr = r_hdr.integer != 0;
5747 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);
5750 void R_Bloom_CopyBloomTexture(float colorscale)
5752 r_refdef.stats.bloom++;
5754 // scale down screen texture to the bloom texture size
5756 R_SetViewport(&r_bloomstate.viewport);
5757 GL_BlendFunc(GL_ONE, GL_ZERO);
5758 GL_Color(colorscale, colorscale, colorscale, 1);
5759 // 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...
5760 switch(vid.renderpath)
5762 case RENDERPATH_GL11:
5763 case RENDERPATH_GL13:
5764 case RENDERPATH_GL20:
5765 case RENDERPATH_SOFT:
5766 case RENDERPATH_GLES2:
5767 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5769 case RENDERPATH_D3D9:
5770 case RENDERPATH_D3D10:
5771 case RENDERPATH_D3D11:
5772 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5775 // TODO: do boxfilter scale-down in shader?
5776 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5777 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5778 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5780 // we now have a bloom image in the framebuffer
5781 // copy it into the bloom image texture for later processing
5782 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);
5783 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5786 void R_Bloom_CopyHDRTexture(void)
5788 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);
5789 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5792 void R_Bloom_MakeTexture(void)
5795 float xoffset, yoffset, r, brighten;
5797 r_refdef.stats.bloom++;
5799 R_ResetViewRendering2D();
5801 // we have a bloom image in the framebuffer
5803 R_SetViewport(&r_bloomstate.viewport);
5805 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5808 r = bound(0, r_bloom_colorexponent.value / x, 1);
5809 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5811 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5812 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5813 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5814 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5816 // copy the vertically blurred bloom view to a texture
5817 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);
5818 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5821 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5822 brighten = r_bloom_brighten.value;
5824 brighten *= r_hdr_range.value;
5825 brighten = sqrt(brighten);
5827 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5828 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5830 for (dir = 0;dir < 2;dir++)
5832 // blend on at multiple vertical offsets to achieve a vertical blur
5833 // TODO: do offset blends using GLSL
5834 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5835 GL_BlendFunc(GL_ONE, GL_ZERO);
5836 for (x = -range;x <= range;x++)
5838 if (!dir){xoffset = 0;yoffset = x;}
5839 else {xoffset = x;yoffset = 0;}
5840 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5841 yoffset /= (float)r_bloomstate.bloomtextureheight;
5842 // compute a texcoord array with the specified x and y offset
5843 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5844 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5845 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5846 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5847 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5848 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5849 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5850 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5851 // this r value looks like a 'dot' particle, fading sharply to
5852 // black at the edges
5853 // (probably not realistic but looks good enough)
5854 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5855 //r = brighten/(range*2+1);
5856 r = brighten / (range * 2 + 1);
5858 r *= (1 - x*x/(float)(range*range));
5859 GL_Color(r, r, r, 1);
5860 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5861 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5862 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5863 GL_BlendFunc(GL_ONE, GL_ONE);
5866 // copy the vertically blurred bloom view to a texture
5867 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);
5868 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5872 void R_HDR_RenderBloomTexture(void)
5874 int oldwidth, oldheight;
5875 float oldcolorscale;
5876 qboolean oldwaterstate;
5878 oldwaterstate = r_waterstate.enabled;
5879 oldcolorscale = r_refdef.view.colorscale;
5880 oldwidth = r_refdef.view.width;
5881 oldheight = r_refdef.view.height;
5882 r_refdef.view.width = r_bloomstate.bloomwidth;
5883 r_refdef.view.height = r_bloomstate.bloomheight;
5885 if(r_hdr.integer < 2)
5886 r_waterstate.enabled = false;
5888 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5889 // TODO: add exposure compensation features
5890 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5892 r_refdef.view.showdebug = false;
5893 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5895 R_ResetViewRendering3D();
5897 R_ClearScreen(r_refdef.fogenabled);
5898 if (r_timereport_active)
5899 R_TimeReport("HDRclear");
5902 if (r_timereport_active)
5903 R_TimeReport("visibility");
5905 // only do secondary renders with HDR if r_hdr is 2 or higher
5906 r_waterstate.numwaterplanes = 0;
5907 if (r_waterstate.enabled)
5908 R_RenderWaterPlanes();
5910 r_refdef.view.showdebug = true;
5912 r_waterstate.numwaterplanes = 0;
5914 R_ResetViewRendering2D();
5916 R_Bloom_CopyHDRTexture();
5917 R_Bloom_MakeTexture();
5919 // restore the view settings
5920 r_waterstate.enabled = oldwaterstate;
5921 r_refdef.view.width = oldwidth;
5922 r_refdef.view.height = oldheight;
5923 r_refdef.view.colorscale = oldcolorscale;
5925 R_ResetViewRendering3D();
5927 R_ClearScreen(r_refdef.fogenabled);
5928 if (r_timereport_active)
5929 R_TimeReport("viewclear");
5932 static void R_BlendView(void)
5934 unsigned int permutation;
5935 float uservecs[4][4];
5937 switch (vid.renderpath)
5939 case RENDERPATH_GL20:
5940 case RENDERPATH_D3D9:
5941 case RENDERPATH_D3D10:
5942 case RENDERPATH_D3D11:
5943 case RENDERPATH_SOFT:
5944 case RENDERPATH_GLES2:
5946 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5947 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5948 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5949 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5950 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5952 if (r_bloomstate.texture_screen)
5954 // make sure the buffer is available
5955 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5957 R_ResetViewRendering2D();
5959 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5961 // declare variables
5963 static float avgspeed;
5965 speed = VectorLength(cl.movement_velocity);
5967 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5968 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5970 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5971 speed = bound(0, speed, 1);
5972 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5974 // calculate values into a standard alpha
5975 cl.motionbluralpha = 1 - exp(-
5977 (r_motionblur.value * speed / 80)
5979 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5982 max(0.0001, cl.time - cl.oldtime) // fps independent
5985 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5986 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5988 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
5990 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5991 GL_Color(1, 1, 1, cl.motionbluralpha);
5992 switch(vid.renderpath)
5994 case RENDERPATH_GL11:
5995 case RENDERPATH_GL13:
5996 case RENDERPATH_GL20:
5997 case RENDERPATH_SOFT:
5998 case RENDERPATH_GLES2:
5999 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6001 case RENDERPATH_D3D9:
6002 case RENDERPATH_D3D10:
6003 case RENDERPATH_D3D11:
6004 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6007 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6008 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6009 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6013 // copy view into the screen texture
6014 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);
6015 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6017 else if (!r_bloomstate.texture_bloom)
6019 // we may still have to do view tint...
6020 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6022 // apply a color tint to the whole view
6023 R_ResetViewRendering2D();
6024 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6025 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6026 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6027 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6028 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6030 break; // no screen processing, no bloom, skip it
6033 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6035 // render simple bloom effect
6036 // copy the screen and shrink it and darken it for the bloom process
6037 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6038 // make the bloom texture
6039 R_Bloom_MakeTexture();
6042 #if _MSC_VER >= 1400
6043 #define sscanf sscanf_s
6045 memset(uservecs, 0, sizeof(uservecs));
6046 if (r_glsl_postprocess_uservec1_enable.integer)
6047 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6048 if (r_glsl_postprocess_uservec2_enable.integer)
6049 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6050 if (r_glsl_postprocess_uservec3_enable.integer)
6051 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6052 if (r_glsl_postprocess_uservec4_enable.integer)
6053 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6055 R_ResetViewRendering2D();
6056 GL_Color(1, 1, 1, 1);
6057 GL_BlendFunc(GL_ONE, GL_ZERO);
6059 switch(vid.renderpath)
6061 case RENDERPATH_GL20:
6062 case RENDERPATH_GLES2:
6063 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6064 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6065 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6066 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6067 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6068 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]);
6069 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6070 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]);
6071 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]);
6072 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]);
6073 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]);
6074 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6075 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6076 if (r_glsl_permutation->loc_BloomColorSubtract >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6078 case RENDERPATH_D3D9:
6080 // 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...
6081 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6082 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6083 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6084 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6085 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6086 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6087 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6088 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6089 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6090 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6091 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6092 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6093 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6094 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6097 case RENDERPATH_D3D10:
6098 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6100 case RENDERPATH_D3D11:
6101 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6103 case RENDERPATH_SOFT:
6104 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6105 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6106 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6107 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6108 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6109 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6110 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6111 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6112 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6113 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6114 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6115 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6116 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6117 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6122 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6123 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6125 case RENDERPATH_GL13:
6126 case RENDERPATH_GL11:
6127 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6129 // apply a color tint to the whole view
6130 R_ResetViewRendering2D();
6131 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6132 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6133 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6134 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6135 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6141 matrix4x4_t r_waterscrollmatrix;
6143 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6145 if (r_refdef.fog_density)
6147 r_refdef.fogcolor[0] = r_refdef.fog_red;
6148 r_refdef.fogcolor[1] = r_refdef.fog_green;
6149 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6151 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6152 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6153 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6154 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6158 VectorCopy(r_refdef.fogcolor, fogvec);
6159 // color.rgb *= ContrastBoost * SceneBrightness;
6160 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6161 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6162 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6163 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6168 void R_UpdateVariables(void)
6172 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6174 r_refdef.farclip = r_farclip_base.value;
6175 if (r_refdef.scene.worldmodel)
6176 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6177 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6179 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6180 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6181 r_refdef.polygonfactor = 0;
6182 r_refdef.polygonoffset = 0;
6183 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6184 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6186 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6187 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6188 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6189 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6190 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6191 if (FAKELIGHT_ENABLED)
6193 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6195 if (r_showsurfaces.integer)
6197 r_refdef.scene.rtworld = false;
6198 r_refdef.scene.rtworldshadows = false;
6199 r_refdef.scene.rtdlight = false;
6200 r_refdef.scene.rtdlightshadows = false;
6201 r_refdef.lightmapintensity = 0;
6204 if (gamemode == GAME_NEHAHRA)
6206 if (gl_fogenable.integer)
6208 r_refdef.oldgl_fogenable = true;
6209 r_refdef.fog_density = gl_fogdensity.value;
6210 r_refdef.fog_red = gl_fogred.value;
6211 r_refdef.fog_green = gl_foggreen.value;
6212 r_refdef.fog_blue = gl_fogblue.value;
6213 r_refdef.fog_alpha = 1;
6214 r_refdef.fog_start = 0;
6215 r_refdef.fog_end = gl_skyclip.value;
6216 r_refdef.fog_height = 1<<30;
6217 r_refdef.fog_fadedepth = 128;
6219 else if (r_refdef.oldgl_fogenable)
6221 r_refdef.oldgl_fogenable = false;
6222 r_refdef.fog_density = 0;
6223 r_refdef.fog_red = 0;
6224 r_refdef.fog_green = 0;
6225 r_refdef.fog_blue = 0;
6226 r_refdef.fog_alpha = 0;
6227 r_refdef.fog_start = 0;
6228 r_refdef.fog_end = 0;
6229 r_refdef.fog_height = 1<<30;
6230 r_refdef.fog_fadedepth = 128;
6234 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6235 r_refdef.fog_start = max(0, r_refdef.fog_start);
6236 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6238 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6240 if (r_refdef.fog_density && r_drawfog.integer)
6242 r_refdef.fogenabled = true;
6243 // this is the point where the fog reaches 0.9986 alpha, which we
6244 // consider a good enough cutoff point for the texture
6245 // (0.9986 * 256 == 255.6)
6246 if (r_fog_exp2.integer)
6247 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6249 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6250 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6251 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6252 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6253 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6254 R_BuildFogHeightTexture();
6255 // fog color was already set
6256 // update the fog texture
6257 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)
6258 R_BuildFogTexture();
6259 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6260 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6263 r_refdef.fogenabled = false;
6265 switch(vid.renderpath)
6267 case RENDERPATH_GL20:
6268 case RENDERPATH_D3D9:
6269 case RENDERPATH_D3D10:
6270 case RENDERPATH_D3D11:
6271 case RENDERPATH_SOFT:
6272 case RENDERPATH_GLES2:
6273 if(v_glslgamma.integer && !vid_gammatables_trivial)
6275 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6277 // build GLSL gamma texture
6278 #define RAMPWIDTH 256
6279 unsigned short ramp[RAMPWIDTH * 3];
6280 unsigned char rampbgr[RAMPWIDTH][4];
6283 r_texture_gammaramps_serial = vid_gammatables_serial;
6285 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6286 for(i = 0; i < RAMPWIDTH; ++i)
6288 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6289 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6290 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6293 if (r_texture_gammaramps)
6295 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6299 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6305 // remove GLSL gamma texture
6308 case RENDERPATH_GL13:
6309 case RENDERPATH_GL11:
6314 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6315 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6321 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6322 if( scenetype != r_currentscenetype ) {
6323 // store the old scenetype
6324 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6325 r_currentscenetype = scenetype;
6326 // move in the new scene
6327 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6336 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6338 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6339 if( scenetype == r_currentscenetype ) {
6340 return &r_refdef.scene;
6342 return &r_scenes_store[ scenetype ];
6351 int dpsoftrast_test;
6352 void R_RenderView(void)
6354 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6356 dpsoftrast_test = r_test.integer;
6358 if (r_timereport_active)
6359 R_TimeReport("start");
6360 r_textureframe++; // used only by R_GetCurrentTexture
6361 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6363 if(R_CompileShader_CheckStaticParms())
6366 if (!r_drawentities.integer)
6367 r_refdef.scene.numentities = 0;
6369 R_AnimCache_ClearCache();
6370 R_FrameData_NewFrame();
6372 /* adjust for stereo display */
6373 if(R_Stereo_Active())
6375 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);
6376 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6379 if (r_refdef.view.isoverlay)
6381 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6382 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6383 R_TimeReport("depthclear");
6385 r_refdef.view.showdebug = false;
6387 r_waterstate.enabled = false;
6388 r_waterstate.numwaterplanes = 0;
6392 r_refdef.view.matrix = originalmatrix;
6398 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6400 r_refdef.view.matrix = originalmatrix;
6401 return; //Host_Error ("R_RenderView: NULL worldmodel");
6404 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6406 R_RenderView_UpdateViewVectors();
6408 R_Shadow_UpdateWorldLightSelection();
6410 R_Bloom_StartFrame();
6411 R_Water_StartFrame();
6414 if (r_timereport_active)
6415 R_TimeReport("viewsetup");
6417 R_ResetViewRendering3D();
6419 if (r_refdef.view.clear || r_refdef.fogenabled)
6421 R_ClearScreen(r_refdef.fogenabled);
6422 if (r_timereport_active)
6423 R_TimeReport("viewclear");
6425 r_refdef.view.clear = true;
6427 // this produces a bloom texture to be used in R_BlendView() later
6428 if (r_hdr.integer && r_bloomstate.bloomwidth)
6430 R_HDR_RenderBloomTexture();
6431 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6432 r_textureframe++; // used only by R_GetCurrentTexture
6435 r_refdef.view.showdebug = true;
6438 if (r_timereport_active)
6439 R_TimeReport("visibility");
6441 r_waterstate.numwaterplanes = 0;
6442 if (r_waterstate.enabled)
6443 R_RenderWaterPlanes();
6446 r_waterstate.numwaterplanes = 0;
6449 if (r_timereport_active)
6450 R_TimeReport("blendview");
6452 GL_Scissor(0, 0, vid.width, vid.height);
6453 GL_ScissorTest(false);
6455 r_refdef.view.matrix = originalmatrix;
6460 void R_RenderWaterPlanes(void)
6462 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6464 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6465 if (r_timereport_active)
6466 R_TimeReport("waterworld");
6469 // don't let sound skip if going slow
6470 if (r_refdef.scene.extraupdate)
6473 R_DrawModelsAddWaterPlanes();
6474 if (r_timereport_active)
6475 R_TimeReport("watermodels");
6477 if (r_waterstate.numwaterplanes)
6479 R_Water_ProcessPlanes();
6480 if (r_timereport_active)
6481 R_TimeReport("waterscenes");
6485 extern void R_DrawLightningBeams (void);
6486 extern void VM_CL_AddPolygonsToMeshQueue (void);
6487 extern void R_DrawPortals (void);
6488 extern cvar_t cl_locs_show;
6489 static void R_DrawLocs(void);
6490 static void R_DrawEntityBBoxes(void);
6491 static void R_DrawModelDecals(void);
6492 extern void R_DrawModelShadows(void);
6493 extern void R_DrawModelShadowMaps(void);
6494 extern cvar_t cl_decals_newsystem;
6495 extern qboolean r_shadow_usingdeferredprepass;
6496 void R_RenderScene(void)
6498 qboolean shadowmapping = false;
6500 if (r_timereport_active)
6501 R_TimeReport("beginscene");
6503 r_refdef.stats.renders++;
6507 // don't let sound skip if going slow
6508 if (r_refdef.scene.extraupdate)
6511 R_MeshQueue_BeginScene();
6515 Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
6517 if (r_timereport_active)
6518 R_TimeReport("skystartframe");
6520 if (cl.csqc_vidvars.drawworld)
6522 // don't let sound skip if going slow
6523 if (r_refdef.scene.extraupdate)
6526 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6528 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6529 if (r_timereport_active)
6530 R_TimeReport("worldsky");
6533 if (R_DrawBrushModelsSky() && r_timereport_active)
6534 R_TimeReport("bmodelsky");
6536 if (skyrendermasked && skyrenderlater)
6538 // we have to force off the water clipping plane while rendering sky
6542 if (r_timereport_active)
6543 R_TimeReport("sky");
6547 R_AnimCache_CacheVisibleEntities();
6548 if (r_timereport_active)
6549 R_TimeReport("animation");
6551 R_Shadow_PrepareLights();
6552 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6553 R_Shadow_PrepareModelShadows();
6554 if (r_timereport_active)
6555 R_TimeReport("preparelights");
6557 if (R_Shadow_ShadowMappingEnabled())
6558 shadowmapping = true;
6560 if (r_shadow_usingdeferredprepass)
6561 R_Shadow_DrawPrepass();
6563 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6565 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6566 if (r_timereport_active)
6567 R_TimeReport("worlddepth");
6569 if (r_depthfirst.integer >= 2)
6571 R_DrawModelsDepth();
6572 if (r_timereport_active)
6573 R_TimeReport("modeldepth");
6576 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6578 R_DrawModelShadowMaps();
6579 R_ResetViewRendering3D();
6580 // don't let sound skip if going slow
6581 if (r_refdef.scene.extraupdate)
6585 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6587 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6588 if (r_timereport_active)
6589 R_TimeReport("world");
6592 // don't let sound skip if going slow
6593 if (r_refdef.scene.extraupdate)
6597 if (r_timereport_active)
6598 R_TimeReport("models");
6600 // don't let sound skip if going slow
6601 if (r_refdef.scene.extraupdate)
6604 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6606 R_DrawModelShadows();
6607 R_ResetViewRendering3D();
6608 // don't let sound skip if going slow
6609 if (r_refdef.scene.extraupdate)
6613 if (!r_shadow_usingdeferredprepass)
6615 R_Shadow_DrawLights();
6616 if (r_timereport_active)
6617 R_TimeReport("rtlights");
6620 // don't let sound skip if going slow
6621 if (r_refdef.scene.extraupdate)
6624 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6626 R_DrawModelShadows();
6627 R_ResetViewRendering3D();
6628 // don't let sound skip if going slow
6629 if (r_refdef.scene.extraupdate)
6633 if (cl.csqc_vidvars.drawworld)
6635 if (cl_decals_newsystem.integer)
6637 R_DrawModelDecals();
6638 if (r_timereport_active)
6639 R_TimeReport("modeldecals");
6644 if (r_timereport_active)
6645 R_TimeReport("decals");
6649 if (r_timereport_active)
6650 R_TimeReport("particles");
6653 if (r_timereport_active)
6654 R_TimeReport("explosions");
6656 R_DrawLightningBeams();
6657 if (r_timereport_active)
6658 R_TimeReport("lightning");
6661 VM_CL_AddPolygonsToMeshQueue();
6663 if (r_refdef.view.showdebug)
6665 if (cl_locs_show.integer)
6668 if (r_timereport_active)
6669 R_TimeReport("showlocs");
6672 if (r_drawportals.integer)
6675 if (r_timereport_active)
6676 R_TimeReport("portals");
6679 if (r_showbboxes.value > 0)
6681 R_DrawEntityBBoxes();
6682 if (r_timereport_active)
6683 R_TimeReport("bboxes");
6687 R_MeshQueue_RenderTransparent();
6688 if (r_timereport_active)
6689 R_TimeReport("drawtrans");
6691 if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0))
6693 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6694 if (r_timereport_active)
6695 R_TimeReport("worlddebug");
6696 R_DrawModelsDebug();
6697 if (r_timereport_active)
6698 R_TimeReport("modeldebug");
6701 if (cl.csqc_vidvars.drawworld)
6703 R_Shadow_DrawCoronas();
6704 if (r_timereport_active)
6705 R_TimeReport("coronas");
6710 GL_DepthTest(false);
6711 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6712 GL_Color(1, 1, 1, 1);
6713 qglBegin(GL_POLYGON);
6714 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6715 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6716 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6717 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6719 qglBegin(GL_POLYGON);
6720 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]);
6721 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]);
6722 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]);
6723 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
6725 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6729 // don't let sound skip if going slow
6730 if (r_refdef.scene.extraupdate)
6733 R_ResetViewRendering2D();
6736 static const unsigned short bboxelements[36] =
6746 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6749 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6751 RSurf_ActiveWorldEntity();
6753 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6754 GL_DepthMask(false);
6755 GL_DepthRange(0, 1);
6756 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6757 // R_Mesh_ResetTextureState();
6759 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6760 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6761 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6762 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6763 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6764 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6765 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6766 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6767 R_FillColors(color4f, 8, cr, cg, cb, ca);
6768 if (r_refdef.fogenabled)
6770 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6772 f1 = RSurf_FogVertex(v);
6774 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6775 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6776 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6779 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6780 R_Mesh_ResetTextureState();
6781 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6782 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6785 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6789 prvm_edict_t *edict;
6790 prvm_prog_t *prog_save = prog;
6792 // this function draws bounding boxes of server entities
6796 GL_CullFace(GL_NONE);
6797 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6801 for (i = 0;i < numsurfaces;i++)
6803 edict = PRVM_EDICT_NUM(surfacelist[i]);
6804 switch ((int)edict->fields.server->solid)
6806 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6807 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6808 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6809 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6810 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6811 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6813 color[3] *= r_showbboxes.value;
6814 color[3] = bound(0, color[3], 1);
6815 GL_DepthTest(!r_showdisabledepthtest.integer);
6816 GL_CullFace(r_refdef.view.cullface_front);
6817 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6823 static void R_DrawEntityBBoxes(void)
6826 prvm_edict_t *edict;
6828 prvm_prog_t *prog_save = prog;
6830 // this function draws bounding boxes of server entities
6836 for (i = 0;i < prog->num_edicts;i++)
6838 edict = PRVM_EDICT_NUM(i);
6839 if (edict->priv.server->free)
6841 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6842 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6844 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6846 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6847 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6853 static const int nomodelelement3i[24] =
6865 static const unsigned short nomodelelement3s[24] =
6877 static const float nomodelvertex3f[6*3] =
6887 static const float nomodelcolor4f[6*4] =
6889 0.0f, 0.0f, 0.5f, 1.0f,
6890 0.0f, 0.0f, 0.5f, 1.0f,
6891 0.0f, 0.5f, 0.0f, 1.0f,
6892 0.0f, 0.5f, 0.0f, 1.0f,
6893 0.5f, 0.0f, 0.0f, 1.0f,
6894 0.5f, 0.0f, 0.0f, 1.0f
6897 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6903 RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
6905 // this is only called once per entity so numsurfaces is always 1, and
6906 // surfacelist is always {0}, so this code does not handle batches
6908 if (rsurface.ent_flags & RENDER_ADDITIVE)
6910 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6911 GL_DepthMask(false);
6913 else if (rsurface.colormod[3] < 1)
6915 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6916 GL_DepthMask(false);
6920 GL_BlendFunc(GL_ONE, GL_ZERO);
6923 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6924 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6925 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6926 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6927 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6928 for (i = 0, c = color4f;i < 6;i++, c += 4)
6930 c[0] *= rsurface.colormod[0];
6931 c[1] *= rsurface.colormod[1];
6932 c[2] *= rsurface.colormod[2];
6933 c[3] *= rsurface.colormod[3];
6935 if (r_refdef.fogenabled)
6937 for (i = 0, c = color4f;i < 6;i++, c += 4)
6939 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6941 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6942 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6943 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6946 // R_Mesh_ResetTextureState();
6947 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6948 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6949 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6952 void R_DrawNoModel(entity_render_t *ent)
6955 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6956 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6957 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6959 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6962 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6964 vec3_t right1, right2, diff, normal;
6966 VectorSubtract (org2, org1, normal);
6968 // calculate 'right' vector for start
6969 VectorSubtract (r_refdef.view.origin, org1, diff);
6970 CrossProduct (normal, diff, right1);
6971 VectorNormalize (right1);
6973 // calculate 'right' vector for end
6974 VectorSubtract (r_refdef.view.origin, org2, diff);
6975 CrossProduct (normal, diff, right2);
6976 VectorNormalize (right2);
6978 vert[ 0] = org1[0] + width * right1[0];
6979 vert[ 1] = org1[1] + width * right1[1];
6980 vert[ 2] = org1[2] + width * right1[2];
6981 vert[ 3] = org1[0] - width * right1[0];
6982 vert[ 4] = org1[1] - width * right1[1];
6983 vert[ 5] = org1[2] - width * right1[2];
6984 vert[ 6] = org2[0] - width * right2[0];
6985 vert[ 7] = org2[1] - width * right2[1];
6986 vert[ 8] = org2[2] - width * right2[2];
6987 vert[ 9] = org2[0] + width * right2[0];
6988 vert[10] = org2[1] + width * right2[1];
6989 vert[11] = org2[2] + width * right2[2];
6992 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
6994 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6995 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6996 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6997 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6998 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
6999 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7000 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7001 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7002 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7003 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7004 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7005 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7008 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7013 VectorSet(v, x, y, z);
7014 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7015 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7017 if (i == mesh->numvertices)
7019 if (mesh->numvertices < mesh->maxvertices)
7021 VectorCopy(v, vertex3f);
7022 mesh->numvertices++;
7024 return mesh->numvertices;
7030 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7034 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7035 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7036 e = mesh->element3i + mesh->numtriangles * 3;
7037 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7039 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7040 if (mesh->numtriangles < mesh->maxtriangles)
7045 mesh->numtriangles++;
7047 element[1] = element[2];
7051 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7055 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7056 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7057 e = mesh->element3i + mesh->numtriangles * 3;
7058 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7060 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7061 if (mesh->numtriangles < mesh->maxtriangles)
7066 mesh->numtriangles++;
7068 element[1] = element[2];
7072 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7073 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7075 int planenum, planenum2;
7078 mplane_t *plane, *plane2;
7080 double temppoints[2][256*3];
7081 // figure out how large a bounding box we need to properly compute this brush
7083 for (w = 0;w < numplanes;w++)
7084 maxdist = max(maxdist, fabs(planes[w].dist));
7085 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7086 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7087 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7091 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7092 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7094 if (planenum2 == planenum)
7096 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);
7099 if (tempnumpoints < 3)
7101 // generate elements forming a triangle fan for this polygon
7102 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7106 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
7108 texturelayer_t *layer;
7109 layer = t->currentlayers + t->currentnumlayers++;
7111 layer->depthmask = depthmask;
7112 layer->blendfunc1 = blendfunc1;
7113 layer->blendfunc2 = blendfunc2;
7114 layer->texture = texture;
7115 layer->texmatrix = *matrix;
7116 layer->color[0] = r;
7117 layer->color[1] = g;
7118 layer->color[2] = b;
7119 layer->color[3] = a;
7122 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7124 if(parms[0] == 0 && parms[1] == 0)
7126 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7127 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7132 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7135 index = parms[2] + r_refdef.scene.time * parms[3];
7136 index -= floor(index);
7137 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7140 case Q3WAVEFUNC_NONE:
7141 case Q3WAVEFUNC_NOISE:
7142 case Q3WAVEFUNC_COUNT:
7145 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7146 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7147 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7148 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7149 case Q3WAVEFUNC_TRIANGLE:
7151 f = index - floor(index);
7162 f = parms[0] + parms[1] * f;
7163 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7164 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7168 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7173 matrix4x4_t matrix, temp;
7174 switch(tcmod->tcmod)
7178 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7179 matrix = r_waterscrollmatrix;
7181 matrix = identitymatrix;
7183 case Q3TCMOD_ENTITYTRANSLATE:
7184 // this is used in Q3 to allow the gamecode to control texcoord
7185 // scrolling on the entity, which is not supported in darkplaces yet.
7186 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7188 case Q3TCMOD_ROTATE:
7189 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7190 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7191 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7194 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7196 case Q3TCMOD_SCROLL:
7197 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7199 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7200 w = (int) tcmod->parms[0];
7201 h = (int) tcmod->parms[1];
7202 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7204 idx = (int) floor(f * w * h);
7205 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7207 case Q3TCMOD_STRETCH:
7208 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7209 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7211 case Q3TCMOD_TRANSFORM:
7212 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7213 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7214 VectorSet(tcmat + 6, 0 , 0 , 1);
7215 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7216 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7218 case Q3TCMOD_TURBULENT:
7219 // this is handled in the RSurf_PrepareVertices function
7220 matrix = identitymatrix;
7224 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7227 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7229 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7230 char name[MAX_QPATH];
7231 skinframe_t *skinframe;
7232 unsigned char pixels[296*194];
7233 strlcpy(cache->name, skinname, sizeof(cache->name));
7234 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7235 if (developer_loading.integer)
7236 Con_Printf("loading %s\n", name);
7237 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7238 if (!skinframe || !skinframe->base)
7241 fs_offset_t filesize;
7243 f = FS_LoadFile(name, tempmempool, true, &filesize);
7246 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7247 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7251 cache->skinframe = skinframe;
7254 texture_t *R_GetCurrentTexture(texture_t *t)
7257 const entity_render_t *ent = rsurface.entity;
7258 dp_model_t *model = ent->model;
7259 q3shaderinfo_layer_tcmod_t *tcmod;
7261 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7262 return t->currentframe;
7263 t->update_lastrenderframe = r_textureframe;
7264 t->update_lastrenderentity = (void *)ent;
7266 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7267 t->camera_entity = ent->entitynumber;
7269 t->camera_entity = 0;
7271 // switch to an alternate material if this is a q1bsp animated material
7273 texture_t *texture = t;
7274 int s = rsurface.ent_skinnum;
7275 if ((unsigned int)s >= (unsigned int)model->numskins)
7277 if (model->skinscenes)
7279 if (model->skinscenes[s].framecount > 1)
7280 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7282 s = model->skinscenes[s].firstframe;
7285 t = t + s * model->num_surfaces;
7288 // use an alternate animation if the entity's frame is not 0,
7289 // and only if the texture has an alternate animation
7290 if (rsurface.ent_alttextures && t->anim_total[1])
7291 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7293 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7295 texture->currentframe = t;
7298 // update currentskinframe to be a qw skin or animation frame
7299 if (rsurface.ent_qwskin >= 0)
7301 i = rsurface.ent_qwskin;
7302 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7304 r_qwskincache_size = cl.maxclients;
7306 Mem_Free(r_qwskincache);
7307 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7309 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7310 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7311 t->currentskinframe = r_qwskincache[i].skinframe;
7312 if (t->currentskinframe == NULL)
7313 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7315 else if (t->numskinframes >= 2)
7316 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7317 if (t->backgroundnumskinframes >= 2)
7318 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7320 t->currentmaterialflags = t->basematerialflags;
7321 t->currentalpha = rsurface.colormod[3];
7322 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7323 t->currentalpha *= r_wateralpha.value;
7324 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7325 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7326 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7327 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7328 if (!(rsurface.ent_flags & RENDER_LIGHT))
7329 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7330 else if (FAKELIGHT_ENABLED)
7332 // no modellight if using fakelight for the map
7334 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7336 // pick a model lighting mode
7337 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7338 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7340 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7342 if (rsurface.ent_flags & RENDER_ADDITIVE)
7343 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7344 else if (t->currentalpha < 1)
7345 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7346 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7347 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7348 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7349 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7350 if (t->backgroundnumskinframes)
7351 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7352 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7354 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7355 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7358 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7359 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7360 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7362 // there is no tcmod
7363 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7365 t->currenttexmatrix = r_waterscrollmatrix;
7366 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7368 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7370 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7371 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7374 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7375 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7376 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7377 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7379 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7380 if (t->currentskinframe->qpixels)
7381 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7382 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7383 if (!t->basetexture)
7384 t->basetexture = r_texture_notexture;
7385 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7386 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7387 t->nmaptexture = t->currentskinframe->nmap;
7388 if (!t->nmaptexture)
7389 t->nmaptexture = r_texture_blanknormalmap;
7390 t->glosstexture = r_texture_black;
7391 t->glowtexture = t->currentskinframe->glow;
7392 t->fogtexture = t->currentskinframe->fog;
7393 t->reflectmasktexture = t->currentskinframe->reflect;
7394 if (t->backgroundnumskinframes)
7396 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7397 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7398 t->backgroundglosstexture = r_texture_black;
7399 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7400 if (!t->backgroundnmaptexture)
7401 t->backgroundnmaptexture = r_texture_blanknormalmap;
7405 t->backgroundbasetexture = r_texture_white;
7406 t->backgroundnmaptexture = r_texture_blanknormalmap;
7407 t->backgroundglosstexture = r_texture_black;
7408 t->backgroundglowtexture = NULL;
7410 t->specularpower = r_shadow_glossexponent.value;
7411 // TODO: store reference values for these in the texture?
7412 t->specularscale = 0;
7413 if (r_shadow_gloss.integer > 0)
7415 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7417 if (r_shadow_glossintensity.value > 0)
7419 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7420 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7421 t->specularscale = r_shadow_glossintensity.value;
7424 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7426 t->glosstexture = r_texture_white;
7427 t->backgroundglosstexture = r_texture_white;
7428 t->specularscale = r_shadow_gloss2intensity.value;
7429 t->specularpower = r_shadow_gloss2exponent.value;
7432 t->specularscale *= t->specularscalemod;
7433 t->specularpower *= t->specularpowermod;
7435 // lightmaps mode looks bad with dlights using actual texturing, so turn
7436 // off the colormap and glossmap, but leave the normalmap on as it still
7437 // accurately represents the shading involved
7438 if (gl_lightmaps.integer)
7440 t->basetexture = r_texture_grey128;
7441 t->pantstexture = r_texture_black;
7442 t->shirttexture = r_texture_black;
7443 t->nmaptexture = r_texture_blanknormalmap;
7444 t->glosstexture = r_texture_black;
7445 t->glowtexture = NULL;
7446 t->fogtexture = NULL;
7447 t->reflectmasktexture = NULL;
7448 t->backgroundbasetexture = NULL;
7449 t->backgroundnmaptexture = r_texture_blanknormalmap;
7450 t->backgroundglosstexture = r_texture_black;
7451 t->backgroundglowtexture = NULL;
7452 t->specularscale = 0;
7453 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7456 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7457 VectorClear(t->dlightcolor);
7458 t->currentnumlayers = 0;
7459 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7461 int blendfunc1, blendfunc2;
7463 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7465 blendfunc1 = GL_SRC_ALPHA;
7466 blendfunc2 = GL_ONE;
7468 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7470 blendfunc1 = GL_SRC_ALPHA;
7471 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7473 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7475 blendfunc1 = t->customblendfunc[0];
7476 blendfunc2 = t->customblendfunc[1];
7480 blendfunc1 = GL_ONE;
7481 blendfunc2 = GL_ZERO;
7483 // don't colormod evilblend textures
7484 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7485 VectorSet(t->lightmapcolor, 1, 1, 1);
7486 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7487 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7489 // fullbright is not affected by r_refdef.lightmapintensity
7490 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]);
7491 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7492 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]);
7493 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7494 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]);
7498 vec3_t ambientcolor;
7500 // set the color tint used for lights affecting this surface
7501 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7503 // q3bsp has no lightmap updates, so the lightstylevalue that
7504 // would normally be baked into the lightmap must be
7505 // applied to the color
7506 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7507 if (model->type == mod_brushq3)
7508 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7509 colorscale *= r_refdef.lightmapintensity;
7510 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7511 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7512 // basic lit geometry
7513 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]);
7514 // add pants/shirt if needed
7515 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7516 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]);
7517 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7518 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]);
7519 // now add ambient passes if needed
7520 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7522 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]);
7523 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7524 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]);
7525 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7526 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]);
7529 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7530 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]);
7531 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7533 // if this is opaque use alpha blend which will darken the earlier
7536 // if this is an alpha blended material, all the earlier passes
7537 // were darkened by fog already, so we only need to add the fog
7538 // color ontop through the fog mask texture
7540 // if this is an additive blended material, all the earlier passes
7541 // were darkened by fog already, and we should not add fog color
7542 // (because the background was not darkened, there is no fog color
7543 // that was lost behind it).
7544 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]);
7548 return t->currentframe;
7551 rsurfacestate_t rsurface;
7553 void RSurf_ActiveWorldEntity(void)
7555 dp_model_t *model = r_refdef.scene.worldmodel;
7556 //if (rsurface.entity == r_refdef.scene.worldentity)
7558 rsurface.entity = r_refdef.scene.worldentity;
7559 rsurface.skeleton = NULL;
7560 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7561 rsurface.ent_skinnum = 0;
7562 rsurface.ent_qwskin = -1;
7563 rsurface.ent_shadertime = 0;
7564 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7565 rsurface.matrix = identitymatrix;
7566 rsurface.inversematrix = identitymatrix;
7567 rsurface.matrixscale = 1;
7568 rsurface.inversematrixscale = 1;
7569 R_EntityMatrix(&identitymatrix);
7570 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7571 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7572 rsurface.fograngerecip = r_refdef.fograngerecip;
7573 rsurface.fogheightfade = r_refdef.fogheightfade;
7574 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7575 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7576 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7577 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7578 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7579 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7580 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7581 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7582 rsurface.colormod[3] = 1;
7583 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);
7584 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7585 rsurface.frameblend[0].lerp = 1;
7586 rsurface.ent_alttextures = false;
7587 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7588 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7589 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7590 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7591 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7592 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7593 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7594 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7595 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7596 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7597 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7598 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7599 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7600 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7601 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7602 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7603 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7604 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7605 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7606 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7607 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7608 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7609 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7610 rsurface.modelelement3i = model->surfmesh.data_element3i;
7611 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7612 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7613 rsurface.modelelement3s = model->surfmesh.data_element3s;
7614 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7615 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7616 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7617 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7618 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7619 rsurface.modelsurfaces = model->data_surfaces;
7620 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7621 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7622 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7623 rsurface.modelgeneratedvertex = false;
7624 rsurface.batchgeneratedvertex = false;
7625 rsurface.batchfirstvertex = 0;
7626 rsurface.batchnumvertices = 0;
7627 rsurface.batchfirsttriangle = 0;
7628 rsurface.batchnumtriangles = 0;
7629 rsurface.batchvertex3f = NULL;
7630 rsurface.batchvertex3f_vertexbuffer = NULL;
7631 rsurface.batchvertex3f_bufferoffset = 0;
7632 rsurface.batchsvector3f = NULL;
7633 rsurface.batchsvector3f_vertexbuffer = NULL;
7634 rsurface.batchsvector3f_bufferoffset = 0;
7635 rsurface.batchtvector3f = NULL;
7636 rsurface.batchtvector3f_vertexbuffer = NULL;
7637 rsurface.batchtvector3f_bufferoffset = 0;
7638 rsurface.batchnormal3f = NULL;
7639 rsurface.batchnormal3f_vertexbuffer = NULL;
7640 rsurface.batchnormal3f_bufferoffset = 0;
7641 rsurface.batchlightmapcolor4f = NULL;
7642 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7643 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7644 rsurface.batchtexcoordtexture2f = NULL;
7645 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7646 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7647 rsurface.batchtexcoordlightmap2f = NULL;
7648 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7649 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7650 rsurface.batchvertexmesh = NULL;
7651 rsurface.batchvertexmeshbuffer = NULL;
7652 rsurface.batchvertex3fbuffer = NULL;
7653 rsurface.batchelement3i = NULL;
7654 rsurface.batchelement3i_indexbuffer = NULL;
7655 rsurface.batchelement3i_bufferoffset = 0;
7656 rsurface.batchelement3s = NULL;
7657 rsurface.batchelement3s_indexbuffer = NULL;
7658 rsurface.batchelement3s_bufferoffset = 0;
7659 rsurface.passcolor4f = NULL;
7660 rsurface.passcolor4f_vertexbuffer = NULL;
7661 rsurface.passcolor4f_bufferoffset = 0;
7664 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7666 dp_model_t *model = ent->model;
7667 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7669 rsurface.entity = (entity_render_t *)ent;
7670 rsurface.skeleton = ent->skeleton;
7671 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7672 rsurface.ent_skinnum = ent->skinnum;
7673 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;
7674 rsurface.ent_shadertime = ent->shadertime;
7675 rsurface.ent_flags = ent->flags;
7676 rsurface.matrix = ent->matrix;
7677 rsurface.inversematrix = ent->inversematrix;
7678 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7679 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7680 R_EntityMatrix(&rsurface.matrix);
7681 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7682 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7683 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7684 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7685 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7686 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7687 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7688 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7689 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7690 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7691 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7692 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7693 rsurface.colormod[3] = ent->alpha;
7694 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7695 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7696 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7697 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7698 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7699 if (ent->model->brush.submodel && !prepass)
7701 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7702 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7704 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7706 if (ent->animcache_vertex3f)
7708 rsurface.modelvertex3f = ent->animcache_vertex3f;
7709 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7710 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7711 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7712 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7713 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7714 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7716 else if (wanttangents)
7718 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7719 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7720 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7721 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7722 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7723 rsurface.modelvertexmesh = NULL;
7724 rsurface.modelvertexmeshbuffer = NULL;
7725 rsurface.modelvertex3fbuffer = NULL;
7727 else if (wantnormals)
7729 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7730 rsurface.modelsvector3f = NULL;
7731 rsurface.modeltvector3f = NULL;
7732 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7733 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7734 rsurface.modelvertexmesh = NULL;
7735 rsurface.modelvertexmeshbuffer = NULL;
7736 rsurface.modelvertex3fbuffer = NULL;
7740 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7741 rsurface.modelsvector3f = NULL;
7742 rsurface.modeltvector3f = NULL;
7743 rsurface.modelnormal3f = NULL;
7744 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7745 rsurface.modelvertexmesh = NULL;
7746 rsurface.modelvertexmeshbuffer = NULL;
7747 rsurface.modelvertex3fbuffer = NULL;
7749 rsurface.modelvertex3f_vertexbuffer = 0;
7750 rsurface.modelvertex3f_bufferoffset = 0;
7751 rsurface.modelsvector3f_vertexbuffer = 0;
7752 rsurface.modelsvector3f_bufferoffset = 0;
7753 rsurface.modeltvector3f_vertexbuffer = 0;
7754 rsurface.modeltvector3f_bufferoffset = 0;
7755 rsurface.modelnormal3f_vertexbuffer = 0;
7756 rsurface.modelnormal3f_bufferoffset = 0;
7757 rsurface.modelgeneratedvertex = true;
7761 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7762 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7763 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7764 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7765 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7766 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7767 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7768 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7769 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7770 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7771 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7772 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7773 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7774 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7775 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7776 rsurface.modelgeneratedvertex = false;
7778 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7779 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7780 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7781 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7782 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7783 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7784 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7785 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7786 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7787 rsurface.modelelement3i = model->surfmesh.data_element3i;
7788 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7789 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7790 rsurface.modelelement3s = model->surfmesh.data_element3s;
7791 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7792 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7793 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7794 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7795 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7796 rsurface.modelsurfaces = model->data_surfaces;
7797 rsurface.batchgeneratedvertex = false;
7798 rsurface.batchfirstvertex = 0;
7799 rsurface.batchnumvertices = 0;
7800 rsurface.batchfirsttriangle = 0;
7801 rsurface.batchnumtriangles = 0;
7802 rsurface.batchvertex3f = NULL;
7803 rsurface.batchvertex3f_vertexbuffer = NULL;
7804 rsurface.batchvertex3f_bufferoffset = 0;
7805 rsurface.batchsvector3f = NULL;
7806 rsurface.batchsvector3f_vertexbuffer = NULL;
7807 rsurface.batchsvector3f_bufferoffset = 0;
7808 rsurface.batchtvector3f = NULL;
7809 rsurface.batchtvector3f_vertexbuffer = NULL;
7810 rsurface.batchtvector3f_bufferoffset = 0;
7811 rsurface.batchnormal3f = NULL;
7812 rsurface.batchnormal3f_vertexbuffer = NULL;
7813 rsurface.batchnormal3f_bufferoffset = 0;
7814 rsurface.batchlightmapcolor4f = NULL;
7815 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7816 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7817 rsurface.batchtexcoordtexture2f = NULL;
7818 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7819 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7820 rsurface.batchtexcoordlightmap2f = NULL;
7821 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7822 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7823 rsurface.batchvertexmesh = NULL;
7824 rsurface.batchvertexmeshbuffer = NULL;
7825 rsurface.batchvertex3fbuffer = NULL;
7826 rsurface.batchelement3i = NULL;
7827 rsurface.batchelement3i_indexbuffer = NULL;
7828 rsurface.batchelement3i_bufferoffset = 0;
7829 rsurface.batchelement3s = NULL;
7830 rsurface.batchelement3s_indexbuffer = NULL;
7831 rsurface.batchelement3s_bufferoffset = 0;
7832 rsurface.passcolor4f = NULL;
7833 rsurface.passcolor4f_vertexbuffer = NULL;
7834 rsurface.passcolor4f_bufferoffset = 0;
7837 void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
7839 rsurface.entity = r_refdef.scene.worldentity;
7840 rsurface.skeleton = NULL;
7841 rsurface.ent_skinnum = 0;
7842 rsurface.ent_qwskin = -1;
7843 rsurface.ent_shadertime = shadertime;
7844 rsurface.ent_flags = entflags;
7845 rsurface.modelnumvertices = numvertices;
7846 rsurface.modelnumtriangles = numtriangles;
7847 rsurface.matrix = *matrix;
7848 rsurface.inversematrix = *inversematrix;
7849 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7850 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7851 R_EntityMatrix(&rsurface.matrix);
7852 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7853 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7854 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7855 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7856 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7857 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7858 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7859 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7860 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7861 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7862 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7863 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7864 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);
7865 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7866 rsurface.frameblend[0].lerp = 1;
7867 rsurface.ent_alttextures = false;
7868 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7869 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7872 rsurface.modelvertex3f = (float *)vertex3f;
7873 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7874 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7875 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7877 else if (wantnormals)
7879 rsurface.modelvertex3f = (float *)vertex3f;
7880 rsurface.modelsvector3f = NULL;
7881 rsurface.modeltvector3f = NULL;
7882 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7886 rsurface.modelvertex3f = (float *)vertex3f;
7887 rsurface.modelsvector3f = NULL;
7888 rsurface.modeltvector3f = NULL;
7889 rsurface.modelnormal3f = NULL;
7891 rsurface.modelvertexmesh = NULL;
7892 rsurface.modelvertexmeshbuffer = NULL;
7893 rsurface.modelvertex3fbuffer = NULL;
7894 rsurface.modelvertex3f_vertexbuffer = 0;
7895 rsurface.modelvertex3f_bufferoffset = 0;
7896 rsurface.modelsvector3f_vertexbuffer = 0;
7897 rsurface.modelsvector3f_bufferoffset = 0;
7898 rsurface.modeltvector3f_vertexbuffer = 0;
7899 rsurface.modeltvector3f_bufferoffset = 0;
7900 rsurface.modelnormal3f_vertexbuffer = 0;
7901 rsurface.modelnormal3f_bufferoffset = 0;
7902 rsurface.modelgeneratedvertex = true;
7903 rsurface.modellightmapcolor4f = (float *)color4f;
7904 rsurface.modellightmapcolor4f_vertexbuffer = 0;
7905 rsurface.modellightmapcolor4f_bufferoffset = 0;
7906 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
7907 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7908 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7909 rsurface.modeltexcoordlightmap2f = NULL;
7910 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7911 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7912 rsurface.modelelement3i = (int *)element3i;
7913 rsurface.modelelement3i_indexbuffer = NULL;
7914 rsurface.modelelement3i_bufferoffset = 0;
7915 rsurface.modelelement3s = (unsigned short *)element3s;
7916 rsurface.modelelement3s_indexbuffer = NULL;
7917 rsurface.modelelement3s_bufferoffset = 0;
7918 rsurface.modellightmapoffsets = NULL;
7919 rsurface.modelsurfaces = NULL;
7920 rsurface.batchgeneratedvertex = false;
7921 rsurface.batchfirstvertex = 0;
7922 rsurface.batchnumvertices = 0;
7923 rsurface.batchfirsttriangle = 0;
7924 rsurface.batchnumtriangles = 0;
7925 rsurface.batchvertex3f = NULL;
7926 rsurface.batchvertex3f_vertexbuffer = NULL;
7927 rsurface.batchvertex3f_bufferoffset = 0;
7928 rsurface.batchsvector3f = NULL;
7929 rsurface.batchsvector3f_vertexbuffer = NULL;
7930 rsurface.batchsvector3f_bufferoffset = 0;
7931 rsurface.batchtvector3f = NULL;
7932 rsurface.batchtvector3f_vertexbuffer = NULL;
7933 rsurface.batchtvector3f_bufferoffset = 0;
7934 rsurface.batchnormal3f = NULL;
7935 rsurface.batchnormal3f_vertexbuffer = NULL;
7936 rsurface.batchnormal3f_bufferoffset = 0;
7937 rsurface.batchlightmapcolor4f = NULL;
7938 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7939 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7940 rsurface.batchtexcoordtexture2f = NULL;
7941 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7942 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7943 rsurface.batchtexcoordlightmap2f = NULL;
7944 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7945 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7946 rsurface.batchvertexmesh = NULL;
7947 rsurface.batchvertexmeshbuffer = NULL;
7948 rsurface.batchvertex3fbuffer = NULL;
7949 rsurface.batchelement3i = NULL;
7950 rsurface.batchelement3i_indexbuffer = NULL;
7951 rsurface.batchelement3i_bufferoffset = 0;
7952 rsurface.batchelement3s = NULL;
7953 rsurface.batchelement3s_indexbuffer = NULL;
7954 rsurface.batchelement3s_bufferoffset = 0;
7955 rsurface.passcolor4f = NULL;
7956 rsurface.passcolor4f_vertexbuffer = NULL;
7957 rsurface.passcolor4f_bufferoffset = 0;
7959 if (rsurface.modelnumvertices && rsurface.modelelement3i)
7961 if ((wantnormals || wanttangents) && !normal3f)
7963 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7964 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7966 if (wanttangents && !svector3f)
7968 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7969 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7970 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 float RSurf_FogPoint(const float *v)
7977 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7978 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7979 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7980 float FogHeightFade = r_refdef.fogheightfade;
7982 unsigned int fogmasktableindex;
7983 if (r_refdef.fogplaneviewabove)
7984 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7986 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7987 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7988 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7991 float RSurf_FogVertex(const float *v)
7993 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7994 float FogPlaneViewDist = rsurface.fogplaneviewdist;
7995 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7996 float FogHeightFade = rsurface.fogheightfade;
7998 unsigned int fogmasktableindex;
7999 if (r_refdef.fogplaneviewabove)
8000 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8002 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8003 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8004 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8007 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8010 for (i = 0;i < numelements;i++)
8011 outelement3i[i] = inelement3i[i] + adjust;
8014 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8015 extern cvar_t gl_vbo;
8016 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8024 int surfacefirsttriangle;
8025 int surfacenumtriangles;
8026 int surfacefirstvertex;
8027 int surfaceendvertex;
8028 int surfacenumvertices;
8029 int batchnumvertices;
8030 int batchnumtriangles;
8034 qboolean dynamicvertex;
8038 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8040 q3shaderinfo_deform_t *deform;
8041 const msurface_t *surface, *firstsurface;
8042 r_vertexmesh_t *vertexmesh;
8043 if (!texturenumsurfaces)
8045 // find vertex range of this surface batch
8047 firstsurface = texturesurfacelist[0];
8048 firsttriangle = firstsurface->num_firsttriangle;
8049 batchnumvertices = 0;
8050 batchnumtriangles = 0;
8051 firstvertex = endvertex = firstsurface->num_firstvertex;
8052 for (i = 0;i < texturenumsurfaces;i++)
8054 surface = texturesurfacelist[i];
8055 if (surface != firstsurface + i)
8057 surfacefirstvertex = surface->num_firstvertex;
8058 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8059 surfacenumvertices = surface->num_vertices;
8060 surfacenumtriangles = surface->num_triangles;
8061 if (firstvertex > surfacefirstvertex)
8062 firstvertex = surfacefirstvertex;
8063 if (endvertex < surfaceendvertex)
8064 endvertex = surfaceendvertex;
8065 batchnumvertices += surfacenumvertices;
8066 batchnumtriangles += surfacenumtriangles;
8069 // we now know the vertex range used, and if there are any gaps in it
8070 rsurface.batchfirstvertex = firstvertex;
8071 rsurface.batchnumvertices = endvertex - firstvertex;
8072 rsurface.batchfirsttriangle = firsttriangle;
8073 rsurface.batchnumtriangles = batchnumtriangles;
8075 // this variable holds flags for which properties have been updated that
8076 // may require regenerating vertexmesh array...
8079 // check if any dynamic vertex processing must occur
8080 dynamicvertex = false;
8082 // if there is a chance of animated vertex colors, it's a dynamic batch
8083 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8085 dynamicvertex = true;
8086 batchneed |= BATCHNEED_NOGAPS;
8087 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8090 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8092 switch (deform->deform)
8095 case Q3DEFORM_PROJECTIONSHADOW:
8096 case Q3DEFORM_TEXT0:
8097 case Q3DEFORM_TEXT1:
8098 case Q3DEFORM_TEXT2:
8099 case Q3DEFORM_TEXT3:
8100 case Q3DEFORM_TEXT4:
8101 case Q3DEFORM_TEXT5:
8102 case Q3DEFORM_TEXT6:
8103 case Q3DEFORM_TEXT7:
8106 case Q3DEFORM_AUTOSPRITE:
8107 dynamicvertex = true;
8108 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8109 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8111 case Q3DEFORM_AUTOSPRITE2:
8112 dynamicvertex = true;
8113 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8114 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8116 case Q3DEFORM_NORMAL:
8117 dynamicvertex = true;
8118 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8119 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8122 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8123 break; // if wavefunc is a nop, ignore this transform
8124 dynamicvertex = true;
8125 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8126 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8128 case Q3DEFORM_BULGE:
8129 dynamicvertex = true;
8130 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8131 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8134 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8135 break; // if wavefunc is a nop, ignore this transform
8136 dynamicvertex = true;
8137 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8138 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8142 switch(rsurface.texture->tcgen.tcgen)
8145 case Q3TCGEN_TEXTURE:
8147 case Q3TCGEN_LIGHTMAP:
8148 dynamicvertex = true;
8149 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8150 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8152 case Q3TCGEN_VECTOR:
8153 dynamicvertex = true;
8154 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8155 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8157 case Q3TCGEN_ENVIRONMENT:
8158 dynamicvertex = true;
8159 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8160 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8163 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8165 dynamicvertex = true;
8166 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8167 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8170 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8172 dynamicvertex = true;
8173 batchneed |= BATCHNEED_NOGAPS;
8174 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8177 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8179 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8180 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8181 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8182 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8183 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8184 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8185 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8188 // when the model data has no vertex buffer (dynamic mesh), we need to
8190 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8191 batchneed |= BATCHNEED_NOGAPS;
8193 // if needsupdate, we have to do a dynamic vertex batch for sure
8194 if (needsupdate & batchneed)
8195 dynamicvertex = true;
8197 // see if we need to build vertexmesh from arrays
8198 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8199 dynamicvertex = true;
8201 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8202 // also some drivers strongly dislike firstvertex
8203 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8204 dynamicvertex = true;
8206 rsurface.batchvertex3f = rsurface.modelvertex3f;
8207 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8208 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8209 rsurface.batchsvector3f = rsurface.modelsvector3f;
8210 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8211 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8212 rsurface.batchtvector3f = rsurface.modeltvector3f;
8213 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8214 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8215 rsurface.batchnormal3f = rsurface.modelnormal3f;
8216 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8217 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8218 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8219 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8220 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8221 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8222 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8223 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8224 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8225 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8226 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8227 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8228 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8229 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8230 rsurface.batchelement3i = rsurface.modelelement3i;
8231 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8232 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8233 rsurface.batchelement3s = rsurface.modelelement3s;
8234 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8235 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8237 // if any dynamic vertex processing has to occur in software, we copy the
8238 // entire surface list together before processing to rebase the vertices
8239 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8241 // if any gaps exist and we do not have a static vertex buffer, we have to
8242 // copy the surface list together to avoid wasting upload bandwidth on the
8243 // vertices in the gaps.
8245 // if gaps exist and we have a static vertex buffer, we still have to
8246 // combine the index buffer ranges into one dynamic index buffer.
8248 // in all cases we end up with data that can be drawn in one call.
8252 // static vertex data, just set pointers...
8253 rsurface.batchgeneratedvertex = false;
8254 // if there are gaps, we want to build a combined index buffer,
8255 // otherwise use the original static buffer with an appropriate offset
8258 // build a new triangle elements array for this batch
8259 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8260 rsurface.batchfirsttriangle = 0;
8262 for (i = 0;i < texturenumsurfaces;i++)
8264 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8265 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8266 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8267 numtriangles += surfacenumtriangles;
8269 rsurface.batchelement3i_indexbuffer = NULL;
8270 rsurface.batchelement3i_bufferoffset = 0;
8271 rsurface.batchelement3s = NULL;
8272 rsurface.batchelement3s_indexbuffer = NULL;
8273 rsurface.batchelement3s_bufferoffset = 0;
8274 if (endvertex <= 65536)
8276 // make a 16bit (unsigned short) index array if possible
8277 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8278 for (i = 0;i < numtriangles*3;i++)
8279 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8285 // something needs software processing, do it for real...
8286 // we only directly handle separate array data in this case and then
8287 // generate interleaved data if needed...
8288 rsurface.batchgeneratedvertex = true;
8290 // now copy the vertex data into a combined array and make an index array
8291 // (this is what Quake3 does all the time)
8292 //if (gaps || rsurface.batchfirstvertex)
8294 rsurface.batchvertex3fbuffer = NULL;
8295 rsurface.batchvertexmesh = NULL;
8296 rsurface.batchvertexmeshbuffer = NULL;
8297 rsurface.batchvertex3f = NULL;
8298 rsurface.batchvertex3f_vertexbuffer = NULL;
8299 rsurface.batchvertex3f_bufferoffset = 0;
8300 rsurface.batchsvector3f = NULL;
8301 rsurface.batchsvector3f_vertexbuffer = NULL;
8302 rsurface.batchsvector3f_bufferoffset = 0;
8303 rsurface.batchtvector3f = NULL;
8304 rsurface.batchtvector3f_vertexbuffer = NULL;
8305 rsurface.batchtvector3f_bufferoffset = 0;
8306 rsurface.batchnormal3f = NULL;
8307 rsurface.batchnormal3f_vertexbuffer = NULL;
8308 rsurface.batchnormal3f_bufferoffset = 0;
8309 rsurface.batchlightmapcolor4f = NULL;
8310 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8311 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8312 rsurface.batchtexcoordtexture2f = NULL;
8313 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8314 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8315 rsurface.batchtexcoordlightmap2f = NULL;
8316 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8317 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8318 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8319 rsurface.batchelement3i_indexbuffer = NULL;
8320 rsurface.batchelement3i_bufferoffset = 0;
8321 rsurface.batchelement3s = NULL;
8322 rsurface.batchelement3s_indexbuffer = NULL;
8323 rsurface.batchelement3s_bufferoffset = 0;
8324 // we'll only be setting up certain arrays as needed
8325 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8326 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8327 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8328 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8329 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8330 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8331 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8333 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8334 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8336 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8337 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8338 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8339 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8340 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8341 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8344 for (i = 0;i < texturenumsurfaces;i++)
8346 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8347 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8348 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8349 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8350 // copy only the data requested
8351 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8352 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8353 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8355 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8356 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8357 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8358 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8359 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8361 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8362 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8364 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8365 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8366 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8367 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8368 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8369 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8371 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8372 numvertices += surfacenumvertices;
8373 numtriangles += surfacenumtriangles;
8376 // generate a 16bit index array as well if possible
8377 // (in general, dynamic batches fit)
8378 if (numvertices <= 65536)
8380 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8381 for (i = 0;i < numtriangles*3;i++)
8382 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8385 // since we've copied everything, the batch now starts at 0
8386 rsurface.batchfirstvertex = 0;
8387 rsurface.batchnumvertices = batchnumvertices;
8388 rsurface.batchfirsttriangle = 0;
8389 rsurface.batchnumtriangles = batchnumtriangles;
8392 // q1bsp surfaces rendered in vertex color mode have to have colors
8393 // calculated based on lightstyles
8394 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8396 // generate color arrays for the surfaces in this list
8401 const unsigned char *lm;
8402 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8403 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8404 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8406 for (i = 0;i < texturenumsurfaces;i++)
8408 surface = texturesurfacelist[i];
8409 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8410 surfacenumvertices = surface->num_vertices;
8411 if (surface->lightmapinfo->samples)
8413 for (j = 0;j < surfacenumvertices;j++)
8415 lm = surface->lightmapinfo->samples + offsets[j];
8416 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8417 VectorScale(lm, scale, c);
8418 if (surface->lightmapinfo->styles[1] != 255)
8420 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8422 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8423 VectorMA(c, scale, lm, c);
8424 if (surface->lightmapinfo->styles[2] != 255)
8427 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8428 VectorMA(c, scale, lm, c);
8429 if (surface->lightmapinfo->styles[3] != 255)
8432 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8433 VectorMA(c, scale, lm, c);
8440 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);
8446 for (j = 0;j < surfacenumvertices;j++)
8448 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8455 // if vertices are deformed (sprite flares and things in maps, possibly
8456 // water waves, bulges and other deformations), modify the copied vertices
8458 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8460 switch (deform->deform)
8463 case Q3DEFORM_PROJECTIONSHADOW:
8464 case Q3DEFORM_TEXT0:
8465 case Q3DEFORM_TEXT1:
8466 case Q3DEFORM_TEXT2:
8467 case Q3DEFORM_TEXT3:
8468 case Q3DEFORM_TEXT4:
8469 case Q3DEFORM_TEXT5:
8470 case Q3DEFORM_TEXT6:
8471 case Q3DEFORM_TEXT7:
8474 case Q3DEFORM_AUTOSPRITE:
8475 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8476 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8477 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8478 VectorNormalize(newforward);
8479 VectorNormalize(newright);
8480 VectorNormalize(newup);
8481 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8482 // rsurface.batchvertex3f_vertexbuffer = NULL;
8483 // rsurface.batchvertex3f_bufferoffset = 0;
8484 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8485 // rsurface.batchsvector3f_vertexbuffer = NULL;
8486 // rsurface.batchsvector3f_bufferoffset = 0;
8487 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8488 // rsurface.batchtvector3f_vertexbuffer = NULL;
8489 // rsurface.batchtvector3f_bufferoffset = 0;
8490 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8491 // rsurface.batchnormal3f_vertexbuffer = NULL;
8492 // rsurface.batchnormal3f_bufferoffset = 0;
8493 // a single autosprite surface can contain multiple sprites...
8494 for (j = 0;j < batchnumvertices - 3;j += 4)
8496 VectorClear(center);
8497 for (i = 0;i < 4;i++)
8498 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8499 VectorScale(center, 0.25f, center);
8500 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8501 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8502 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8503 for (i = 0;i < 4;i++)
8505 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8506 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8509 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8510 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8511 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8513 case Q3DEFORM_AUTOSPRITE2:
8514 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8515 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8516 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8517 VectorNormalize(newforward);
8518 VectorNormalize(newright);
8519 VectorNormalize(newup);
8520 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8521 // rsurface.batchvertex3f_vertexbuffer = NULL;
8522 // rsurface.batchvertex3f_bufferoffset = 0;
8524 const float *v1, *v2;
8534 memset(shortest, 0, sizeof(shortest));
8535 // a single autosprite surface can contain multiple sprites...
8536 for (j = 0;j < batchnumvertices - 3;j += 4)
8538 VectorClear(center);
8539 for (i = 0;i < 4;i++)
8540 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8541 VectorScale(center, 0.25f, center);
8542 // find the two shortest edges, then use them to define the
8543 // axis vectors for rotating around the central axis
8544 for (i = 0;i < 6;i++)
8546 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8547 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8548 l = VectorDistance2(v1, v2);
8549 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8551 l += (1.0f / 1024.0f);
8552 if (shortest[0].length2 > l || i == 0)
8554 shortest[1] = shortest[0];
8555 shortest[0].length2 = l;
8556 shortest[0].v1 = v1;
8557 shortest[0].v2 = v2;
8559 else if (shortest[1].length2 > l || i == 1)
8561 shortest[1].length2 = l;
8562 shortest[1].v1 = v1;
8563 shortest[1].v2 = v2;
8566 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8567 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8568 // this calculates the right vector from the shortest edge
8569 // and the up vector from the edge midpoints
8570 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8571 VectorNormalize(right);
8572 VectorSubtract(end, start, up);
8573 VectorNormalize(up);
8574 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8575 VectorSubtract(rsurface.localvieworigin, center, forward);
8576 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8577 VectorNegate(forward, forward);
8578 VectorReflect(forward, 0, up, forward);
8579 VectorNormalize(forward);
8580 CrossProduct(up, forward, newright);
8581 VectorNormalize(newright);
8582 // rotate the quad around the up axis vector, this is made
8583 // especially easy by the fact we know the quad is flat,
8584 // so we only have to subtract the center position and
8585 // measure distance along the right vector, and then
8586 // multiply that by the newright vector and add back the
8588 // we also need to subtract the old position to undo the
8589 // displacement from the center, which we do with a
8590 // DotProduct, the subtraction/addition of center is also
8591 // optimized into DotProducts here
8592 l = DotProduct(right, center);
8593 for (i = 0;i < 4;i++)
8595 v1 = rsurface.batchvertex3f + 3*(j+i);
8596 f = DotProduct(right, v1) - l;
8597 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8601 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8603 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8604 // rsurface.batchnormal3f_vertexbuffer = NULL;
8605 // rsurface.batchnormal3f_bufferoffset = 0;
8606 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8608 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8610 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8611 // rsurface.batchsvector3f_vertexbuffer = NULL;
8612 // rsurface.batchsvector3f_bufferoffset = 0;
8613 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8614 // rsurface.batchtvector3f_vertexbuffer = NULL;
8615 // rsurface.batchtvector3f_bufferoffset = 0;
8616 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);
8619 case Q3DEFORM_NORMAL:
8620 // deform the normals to make reflections wavey
8621 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8622 rsurface.batchnormal3f_vertexbuffer = NULL;
8623 rsurface.batchnormal3f_bufferoffset = 0;
8624 for (j = 0;j < batchnumvertices;j++)
8627 float *normal = rsurface.batchnormal3f + 3*j;
8628 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8629 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8630 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]);
8631 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]);
8632 VectorNormalize(normal);
8634 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8636 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8637 // rsurface.batchsvector3f_vertexbuffer = NULL;
8638 // rsurface.batchsvector3f_bufferoffset = 0;
8639 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8640 // rsurface.batchtvector3f_vertexbuffer = NULL;
8641 // rsurface.batchtvector3f_bufferoffset = 0;
8642 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);
8646 // deform vertex array to make wavey water and flags and such
8647 waveparms[0] = deform->waveparms[0];
8648 waveparms[1] = deform->waveparms[1];
8649 waveparms[2] = deform->waveparms[2];
8650 waveparms[3] = deform->waveparms[3];
8651 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8652 break; // if wavefunc is a nop, don't make a dynamic vertex array
8653 // this is how a divisor of vertex influence on deformation
8654 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8655 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8656 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8657 // rsurface.batchvertex3f_vertexbuffer = NULL;
8658 // rsurface.batchvertex3f_bufferoffset = 0;
8659 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8660 // rsurface.batchnormal3f_vertexbuffer = NULL;
8661 // rsurface.batchnormal3f_bufferoffset = 0;
8662 for (j = 0;j < batchnumvertices;j++)
8664 // if the wavefunc depends on time, evaluate it per-vertex
8667 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8668 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8670 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8672 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8673 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8674 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8676 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8677 // rsurface.batchsvector3f_vertexbuffer = NULL;
8678 // rsurface.batchsvector3f_bufferoffset = 0;
8679 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8680 // rsurface.batchtvector3f_vertexbuffer = NULL;
8681 // rsurface.batchtvector3f_bufferoffset = 0;
8682 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);
8685 case Q3DEFORM_BULGE:
8686 // deform vertex array to make the surface have moving bulges
8687 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8688 // rsurface.batchvertex3f_vertexbuffer = NULL;
8689 // rsurface.batchvertex3f_bufferoffset = 0;
8690 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8691 // rsurface.batchnormal3f_vertexbuffer = NULL;
8692 // rsurface.batchnormal3f_bufferoffset = 0;
8693 for (j = 0;j < batchnumvertices;j++)
8695 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8696 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8698 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8699 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8700 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8702 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8703 // rsurface.batchsvector3f_vertexbuffer = NULL;
8704 // rsurface.batchsvector3f_bufferoffset = 0;
8705 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8706 // rsurface.batchtvector3f_vertexbuffer = NULL;
8707 // rsurface.batchtvector3f_bufferoffset = 0;
8708 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);
8712 // deform vertex array
8713 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8714 break; // if wavefunc is a nop, don't make a dynamic vertex array
8715 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8716 VectorScale(deform->parms, scale, waveparms);
8717 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8718 // rsurface.batchvertex3f_vertexbuffer = NULL;
8719 // rsurface.batchvertex3f_bufferoffset = 0;
8720 for (j = 0;j < batchnumvertices;j++)
8721 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8726 // generate texcoords based on the chosen texcoord source
8727 switch(rsurface.texture->tcgen.tcgen)
8730 case Q3TCGEN_TEXTURE:
8732 case Q3TCGEN_LIGHTMAP:
8733 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8734 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8735 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8736 if (rsurface.batchtexcoordlightmap2f)
8737 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8739 case Q3TCGEN_VECTOR:
8740 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8741 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8742 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8743 for (j = 0;j < batchnumvertices;j++)
8745 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8746 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8749 case Q3TCGEN_ENVIRONMENT:
8750 // make environment reflections using a spheremap
8751 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8752 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8753 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8754 for (j = 0;j < batchnumvertices;j++)
8756 // identical to Q3A's method, but executed in worldspace so
8757 // carried models can be shiny too
8759 float viewer[3], d, reflected[3], worldreflected[3];
8761 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8762 // VectorNormalize(viewer);
8764 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8766 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8767 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8768 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8769 // note: this is proportinal to viewer, so we can normalize later
8771 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8772 VectorNormalize(worldreflected);
8774 // note: this sphere map only uses world x and z!
8775 // so positive and negative y will LOOK THE SAME.
8776 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8777 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8781 // the only tcmod that needs software vertex processing is turbulent, so
8782 // check for it here and apply the changes if needed
8783 // and we only support that as the first one
8784 // (handling a mixture of turbulent and other tcmods would be problematic
8785 // without punting it entirely to a software path)
8786 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8788 amplitude = rsurface.texture->tcmods[0].parms[1];
8789 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8790 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8791 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8792 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8793 for (j = 0;j < batchnumvertices;j++)
8795 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);
8796 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8800 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8802 // convert the modified arrays to vertex structs
8803 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8804 // rsurface.batchvertexmeshbuffer = NULL;
8805 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8806 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8807 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8808 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8809 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8810 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8811 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8813 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8815 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8816 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8819 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8820 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8821 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8822 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8823 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8824 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8825 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8826 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8827 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8831 void RSurf_DrawBatch(void)
8833 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8834 // through the pipeline, killing it earlier in the pipeline would have
8835 // per-surface overhead rather than per-batch overhead, so it's best to
8836 // reject it here, before it hits glDraw.
8837 if (rsurface.batchnumtriangles == 0)
8840 // batch debugging code
8841 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8847 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8848 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8851 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8853 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8855 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8856 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);
8863 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);
8866 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8868 // pick the closest matching water plane
8869 int planeindex, vertexindex, bestplaneindex = -1;
8873 r_waterstate_waterplane_t *p;
8874 qboolean prepared = false;
8876 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8878 if(p->camera_entity != rsurface.texture->camera_entity)
8883 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8885 if(rsurface.batchnumvertices == 0)
8888 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8890 Matrix4x4_Transform(&rsurface.matrix, v, vert);
8891 d += fabs(PlaneDiff(vert, &p->plane));
8893 if (bestd > d || bestplaneindex < 0)
8896 bestplaneindex = planeindex;
8899 return bestplaneindex;
8900 // NOTE: this MAY return a totally unrelated water plane; we can ignore
8901 // this situation though, as it might be better to render single larger
8902 // batches with useless stuff (backface culled for example) than to
8903 // render multiple smaller batches
8906 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8909 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8910 rsurface.passcolor4f_vertexbuffer = 0;
8911 rsurface.passcolor4f_bufferoffset = 0;
8912 for (i = 0;i < rsurface.batchnumvertices;i++)
8913 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8916 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8923 if (rsurface.passcolor4f)
8925 // generate color arrays
8926 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8927 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8928 rsurface.passcolor4f_vertexbuffer = 0;
8929 rsurface.passcolor4f_bufferoffset = 0;
8930 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
8932 f = RSurf_FogVertex(v);
8941 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8942 rsurface.passcolor4f_vertexbuffer = 0;
8943 rsurface.passcolor4f_bufferoffset = 0;
8944 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8946 f = RSurf_FogVertex(v);
8955 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8962 if (!rsurface.passcolor4f)
8964 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8965 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8966 rsurface.passcolor4f_vertexbuffer = 0;
8967 rsurface.passcolor4f_bufferoffset = 0;
8968 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
8970 f = RSurf_FogVertex(v);
8971 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8972 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8973 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8978 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
8983 if (!rsurface.passcolor4f)
8985 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8986 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8987 rsurface.passcolor4f_vertexbuffer = 0;
8988 rsurface.passcolor4f_bufferoffset = 0;
8989 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
8998 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9003 if (!rsurface.passcolor4f)
9005 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9006 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9007 rsurface.passcolor4f_vertexbuffer = 0;
9008 rsurface.passcolor4f_bufferoffset = 0;
9009 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9011 c2[0] = c[0] + r_refdef.scene.ambient;
9012 c2[1] = c[1] + r_refdef.scene.ambient;
9013 c2[2] = c[2] + r_refdef.scene.ambient;
9018 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9021 rsurface.passcolor4f = NULL;
9022 rsurface.passcolor4f_vertexbuffer = 0;
9023 rsurface.passcolor4f_bufferoffset = 0;
9024 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9025 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9026 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9027 GL_Color(r, g, b, a);
9028 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9032 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9034 // TODO: optimize applyfog && applycolor case
9035 // just apply fog if necessary, and tint the fog color array if necessary
9036 rsurface.passcolor4f = NULL;
9037 rsurface.passcolor4f_vertexbuffer = 0;
9038 rsurface.passcolor4f_bufferoffset = 0;
9039 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9040 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9041 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9042 GL_Color(r, g, b, a);
9046 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9049 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9050 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9051 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9052 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9053 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9054 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9055 GL_Color(r, g, b, a);
9059 static void RSurf_DrawBatch_GL11_ClampColor(void)
9064 if (!rsurface.passcolor4f)
9066 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9068 c2[0] = bound(0.0f, c1[0], 1.0f);
9069 c2[1] = bound(0.0f, c1[1], 1.0f);
9070 c2[2] = bound(0.0f, c1[2], 1.0f);
9071 c2[3] = bound(0.0f, c1[3], 1.0f);
9075 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9085 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9086 rsurface.passcolor4f_vertexbuffer = 0;
9087 rsurface.passcolor4f_bufferoffset = 0;
9088 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
9090 f = -DotProduct(r_refdef.view.forward, n);
9092 f = f * 0.85 + 0.15; // work around so stuff won't get black
9093 f *= r_refdef.lightmapintensity;
9094 Vector4Set(c, f, f, f, 1);
9098 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9100 RSurf_DrawBatch_GL11_ApplyFakeLight();
9101 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9102 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9103 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9104 GL_Color(r, g, b, a);
9108 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9116 vec3_t ambientcolor;
9117 vec3_t diffusecolor;
9121 VectorCopy(rsurface.modellight_lightdir, lightdir);
9122 f = 0.5f * r_refdef.lightmapintensity;
9123 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9124 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9125 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9126 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9127 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9128 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9130 if (VectorLength2(diffusecolor) > 0)
9132 // q3-style directional shading
9133 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9134 rsurface.passcolor4f_vertexbuffer = 0;
9135 rsurface.passcolor4f_bufferoffset = 0;
9136 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
9138 if ((f = DotProduct(n, lightdir)) > 0)
9139 VectorMA(ambientcolor, f, diffusecolor, c);
9141 VectorCopy(ambientcolor, c);
9148 *applycolor = false;
9152 *r = ambientcolor[0];
9153 *g = ambientcolor[1];
9154 *b = ambientcolor[2];
9155 rsurface.passcolor4f = NULL;
9156 rsurface.passcolor4f_vertexbuffer = 0;
9157 rsurface.passcolor4f_bufferoffset = 0;
9161 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9163 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9164 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9165 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9166 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9167 GL_Color(r, g, b, a);
9171 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9177 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9179 f = 1 - RSurf_FogVertex(v);
9187 void RSurf_SetupDepthAndCulling(void)
9189 // submodels are biased to avoid z-fighting with world surfaces that they
9190 // may be exactly overlapping (avoids z-fighting artifacts on certain
9191 // doors and things in Quake maps)
9192 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9193 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9194 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9195 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9198 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9200 // transparent sky would be ridiculous
9201 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9203 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9204 skyrenderlater = true;
9205 RSurf_SetupDepthAndCulling();
9207 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9208 // skymasking on them, and Quake3 never did sky masking (unlike
9209 // software Quake and software Quake2), so disable the sky masking
9210 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9211 // and skymasking also looks very bad when noclipping outside the
9212 // level, so don't use it then either.
9213 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9215 R_Mesh_ResetTextureState();
9216 if (skyrendermasked)
9218 R_SetupShader_DepthOrShadow();
9219 // depth-only (masking)
9220 GL_ColorMask(0,0,0,0);
9221 // just to make sure that braindead drivers don't draw
9222 // anything despite that colormask...
9223 GL_BlendFunc(GL_ZERO, GL_ONE);
9224 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9225 if (rsurface.batchvertex3fbuffer)
9226 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9228 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9232 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9234 GL_BlendFunc(GL_ONE, GL_ZERO);
9235 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9236 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9237 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9240 if (skyrendermasked)
9241 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9243 R_Mesh_ResetTextureState();
9244 GL_Color(1, 1, 1, 1);
9247 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9248 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9249 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9251 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9255 // render screenspace normalmap to texture
9257 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9262 // bind lightmap texture
9264 // water/refraction/reflection/camera surfaces have to be handled specially
9265 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9267 int start, end, startplaneindex;
9268 for (start = 0;start < texturenumsurfaces;start = end)
9270 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9271 if(startplaneindex < 0)
9273 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9274 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9278 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9280 // now that we have a batch using the same planeindex, render it
9281 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9283 // render water or distortion background
9285 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
9287 // blend surface on top
9288 GL_DepthMask(false);
9289 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9292 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9294 // render surface with reflection texture as input
9295 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9296 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));
9303 // render surface batch normally
9304 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9305 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9309 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9311 // OpenGL 1.3 path - anything not completely ancient
9312 qboolean applycolor;
9315 const texturelayer_t *layer;
9316 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);
9317 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9319 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9322 int layertexrgbscale;
9323 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9325 if (layerindex == 0)
9329 GL_AlphaTest(false);
9330 GL_DepthFunc(GL_EQUAL);
9333 GL_DepthMask(layer->depthmask && writedepth);
9334 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9335 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9337 layertexrgbscale = 4;
9338 VectorScale(layer->color, 0.25f, layercolor);
9340 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9342 layertexrgbscale = 2;
9343 VectorScale(layer->color, 0.5f, layercolor);
9347 layertexrgbscale = 1;
9348 VectorScale(layer->color, 1.0f, layercolor);
9350 layercolor[3] = layer->color[3];
9351 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9352 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9353 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9354 switch (layer->type)
9356 case TEXTURELAYERTYPE_LITTEXTURE:
9357 // single-pass lightmapped texture with 2x rgbscale
9358 R_Mesh_TexBind(0, r_texture_white);
9359 R_Mesh_TexMatrix(0, NULL);
9360 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9361 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9362 R_Mesh_TexBind(1, layer->texture);
9363 R_Mesh_TexMatrix(1, &layer->texmatrix);
9364 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9365 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9366 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9367 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9368 else if (FAKELIGHT_ENABLED)
9369 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9370 else if (rsurface.uselightmaptexture)
9371 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9373 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9375 case TEXTURELAYERTYPE_TEXTURE:
9376 // singletexture unlit texture with transparency support
9377 R_Mesh_TexBind(0, layer->texture);
9378 R_Mesh_TexMatrix(0, &layer->texmatrix);
9379 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9380 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9381 R_Mesh_TexBind(1, 0);
9382 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9383 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9385 case TEXTURELAYERTYPE_FOG:
9386 // singletexture fogging
9389 R_Mesh_TexBind(0, layer->texture);
9390 R_Mesh_TexMatrix(0, &layer->texmatrix);
9391 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9392 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9396 R_Mesh_TexBind(0, 0);
9397 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9399 R_Mesh_TexBind(1, 0);
9400 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9401 // generate a color array for the fog pass
9402 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9403 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9407 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9410 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9412 GL_DepthFunc(GL_LEQUAL);
9413 GL_AlphaTest(false);
9417 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9419 // OpenGL 1.1 - crusty old voodoo path
9422 const texturelayer_t *layer;
9423 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);
9424 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9426 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9428 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9430 if (layerindex == 0)
9434 GL_AlphaTest(false);
9435 GL_DepthFunc(GL_EQUAL);
9438 GL_DepthMask(layer->depthmask && writedepth);
9439 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9440 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9441 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9442 switch (layer->type)
9444 case TEXTURELAYERTYPE_LITTEXTURE:
9445 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9447 // two-pass lit texture with 2x rgbscale
9448 // first the lightmap pass
9449 R_Mesh_TexBind(0, r_texture_white);
9450 R_Mesh_TexMatrix(0, NULL);
9451 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9452 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9453 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9454 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9455 else if (FAKELIGHT_ENABLED)
9456 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9457 else if (rsurface.uselightmaptexture)
9458 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9460 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9461 // then apply the texture to it
9462 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9463 R_Mesh_TexBind(0, layer->texture);
9464 R_Mesh_TexMatrix(0, &layer->texmatrix);
9465 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9466 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9467 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);
9471 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9472 R_Mesh_TexBind(0, layer->texture);
9473 R_Mesh_TexMatrix(0, &layer->texmatrix);
9474 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9475 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9476 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9477 RSurf_DrawBatch_GL11_VertexShade(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
9479 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);
9482 case TEXTURELAYERTYPE_TEXTURE:
9483 // singletexture unlit texture with transparency support
9484 R_Mesh_TexBind(0, layer->texture);
9485 R_Mesh_TexMatrix(0, &layer->texmatrix);
9486 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9487 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9488 RSurf_DrawBatch_GL11_Unlit(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
9490 case TEXTURELAYERTYPE_FOG:
9491 // singletexture fogging
9494 R_Mesh_TexBind(0, layer->texture);
9495 R_Mesh_TexMatrix(0, &layer->texmatrix);
9496 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9497 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9501 R_Mesh_TexBind(0, 0);
9502 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9504 // generate a color array for the fog pass
9505 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9506 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9510 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9513 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9515 GL_DepthFunc(GL_LEQUAL);
9516 GL_AlphaTest(false);
9520 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9524 r_vertexgeneric_t *batchvertex;
9527 // R_Mesh_ResetTextureState();
9528 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9530 if(rsurface.texture && rsurface.texture->currentskinframe)
9532 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9533 c[3] *= rsurface.texture->currentalpha;
9543 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9545 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9546 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9547 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9550 // brighten it up (as texture value 127 means "unlit")
9551 c[0] *= 2 * r_refdef.view.colorscale;
9552 c[1] *= 2 * r_refdef.view.colorscale;
9553 c[2] *= 2 * r_refdef.view.colorscale;
9555 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9556 c[3] *= r_wateralpha.value;
9558 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9560 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9561 GL_DepthMask(false);
9563 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9565 GL_BlendFunc(GL_ONE, GL_ONE);
9566 GL_DepthMask(false);
9568 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9570 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9571 GL_DepthMask(false);
9573 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9575 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9576 GL_DepthMask(false);
9580 GL_BlendFunc(GL_ONE, GL_ZERO);
9581 GL_DepthMask(writedepth);
9584 if (r_showsurfaces.integer == 3)
9586 rsurface.passcolor4f = NULL;
9588 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9590 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9592 rsurface.passcolor4f = NULL;
9593 rsurface.passcolor4f_vertexbuffer = 0;
9594 rsurface.passcolor4f_bufferoffset = 0;
9596 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9598 qboolean applycolor = true;
9601 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9603 r_refdef.lightmapintensity = 1;
9604 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9605 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9607 else if (FAKELIGHT_ENABLED)
9609 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9611 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9612 RSurf_DrawBatch_GL11_ApplyFakeLight();
9613 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9617 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9619 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9620 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9621 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9624 if(!rsurface.passcolor4f)
9625 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9627 RSurf_DrawBatch_GL11_ApplyAmbient();
9628 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9629 if(r_refdef.fogenabled)
9630 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9631 RSurf_DrawBatch_GL11_ClampColor();
9633 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9634 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9637 else if (!r_refdef.view.showdebug)
9639 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9640 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9641 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9643 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9644 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9646 R_Mesh_PrepareVertices_Generic_Unlock();
9649 else if (r_showsurfaces.integer == 4)
9651 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9652 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9653 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9655 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9656 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9657 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9659 R_Mesh_PrepareVertices_Generic_Unlock();
9662 else if (r_showsurfaces.integer == 2)
9665 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9666 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9667 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9669 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9670 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9671 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9672 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9673 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9674 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9675 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9677 R_Mesh_PrepareVertices_Generic_Unlock();
9678 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9682 int texturesurfaceindex;
9684 const msurface_t *surface;
9685 float surfacecolor4f[4];
9686 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9687 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9689 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9691 surface = texturesurfacelist[texturesurfaceindex];
9692 k = (int)(((size_t)surface) / sizeof(msurface_t));
9693 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9694 for (j = 0;j < surface->num_vertices;j++)
9696 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9697 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9701 R_Mesh_PrepareVertices_Generic_Unlock();
9706 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9709 RSurf_SetupDepthAndCulling();
9710 if (r_showsurfaces.integer)
9712 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9715 switch (vid.renderpath)
9717 case RENDERPATH_GL20:
9718 case RENDERPATH_D3D9:
9719 case RENDERPATH_D3D10:
9720 case RENDERPATH_D3D11:
9721 case RENDERPATH_SOFT:
9722 case RENDERPATH_GLES2:
9723 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9725 case RENDERPATH_GL13:
9726 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9728 case RENDERPATH_GL11:
9729 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9735 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9738 RSurf_SetupDepthAndCulling();
9739 if (r_showsurfaces.integer)
9741 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9744 switch (vid.renderpath)
9746 case RENDERPATH_GL20:
9747 case RENDERPATH_D3D9:
9748 case RENDERPATH_D3D10:
9749 case RENDERPATH_D3D11:
9750 case RENDERPATH_SOFT:
9751 case RENDERPATH_GLES2:
9752 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9754 case RENDERPATH_GL13:
9755 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9757 case RENDERPATH_GL11:
9758 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9764 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9767 int texturenumsurfaces, endsurface;
9769 const msurface_t *surface;
9770 #define MAXBATCH_TRANSPARENTSURFACES 256
9771 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9773 // if the model is static it doesn't matter what value we give for
9774 // wantnormals and wanttangents, so this logic uses only rules applicable
9775 // to a model, knowing that they are meaningless otherwise
9776 if (ent == r_refdef.scene.worldentity)
9777 RSurf_ActiveWorldEntity();
9778 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9779 RSurf_ActiveModelEntity(ent, false, false, false);
9782 switch (vid.renderpath)
9784 case RENDERPATH_GL20:
9785 case RENDERPATH_D3D9:
9786 case RENDERPATH_D3D10:
9787 case RENDERPATH_D3D11:
9788 case RENDERPATH_SOFT:
9789 case RENDERPATH_GLES2:
9790 RSurf_ActiveModelEntity(ent, true, true, false);
9792 case RENDERPATH_GL13:
9793 case RENDERPATH_GL11:
9794 RSurf_ActiveModelEntity(ent, true, false, false);
9799 if (r_transparentdepthmasking.integer)
9801 qboolean setup = false;
9802 for (i = 0;i < numsurfaces;i = j)
9805 surface = rsurface.modelsurfaces + surfacelist[i];
9806 texture = surface->texture;
9807 rsurface.texture = R_GetCurrentTexture(texture);
9808 rsurface.lightmaptexture = NULL;
9809 rsurface.deluxemaptexture = NULL;
9810 rsurface.uselightmaptexture = false;
9811 // scan ahead until we find a different texture
9812 endsurface = min(i + 1024, numsurfaces);
9813 texturenumsurfaces = 0;
9814 texturesurfacelist[texturenumsurfaces++] = surface;
9815 for (;j < endsurface;j++)
9817 surface = rsurface.modelsurfaces + surfacelist[j];
9818 if (texture != surface->texture)
9820 texturesurfacelist[texturenumsurfaces++] = surface;
9822 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9824 // render the range of surfaces as depth
9828 GL_ColorMask(0,0,0,0);
9831 GL_BlendFunc(GL_ONE, GL_ZERO);
9833 // R_Mesh_ResetTextureState();
9834 R_SetupShader_DepthOrShadow();
9836 RSurf_SetupDepthAndCulling();
9837 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9838 if (rsurface.batchvertex3fbuffer)
9839 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9841 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9845 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9848 for (i = 0;i < numsurfaces;i = j)
9851 surface = rsurface.modelsurfaces + surfacelist[i];
9852 texture = surface->texture;
9853 rsurface.texture = R_GetCurrentTexture(texture);
9854 // scan ahead until we find a different texture
9855 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9856 texturenumsurfaces = 0;
9857 texturesurfacelist[texturenumsurfaces++] = surface;
9858 if(FAKELIGHT_ENABLED)
9860 rsurface.lightmaptexture = NULL;
9861 rsurface.deluxemaptexture = NULL;
9862 rsurface.uselightmaptexture = false;
9863 for (;j < endsurface;j++)
9865 surface = rsurface.modelsurfaces + surfacelist[j];
9866 if (texture != surface->texture)
9868 texturesurfacelist[texturenumsurfaces++] = surface;
9873 rsurface.lightmaptexture = surface->lightmaptexture;
9874 rsurface.deluxemaptexture = surface->deluxemaptexture;
9875 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9876 for (;j < endsurface;j++)
9878 surface = rsurface.modelsurfaces + surfacelist[j];
9879 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9881 texturesurfacelist[texturenumsurfaces++] = surface;
9884 // render the range of surfaces
9885 if (ent == r_refdef.scene.worldentity)
9886 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9888 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9890 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9893 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9895 // transparent surfaces get pushed off into the transparent queue
9896 int surfacelistindex;
9897 const msurface_t *surface;
9898 vec3_t tempcenter, center;
9899 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9901 surface = texturesurfacelist[surfacelistindex];
9902 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9903 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9904 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9905 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9906 if (queueentity->transparent_offset) // transparent offset
9908 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9909 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9910 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9912 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9916 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9918 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9920 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9922 RSurf_SetupDepthAndCulling();
9923 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9924 if (rsurface.batchvertex3fbuffer)
9925 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9927 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9931 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9933 const entity_render_t *queueentity = r_refdef.scene.worldentity;
9936 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9939 if (!rsurface.texture->currentnumlayers)
9941 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9942 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9944 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9946 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9947 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9948 else if (!rsurface.texture->currentnumlayers)
9950 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9952 // in the deferred case, transparent surfaces were queued during prepass
9953 if (!r_shadow_usingdeferredprepass)
9954 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9958 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9959 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9964 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9968 R_FrameData_SetMark();
9969 // break the surface list down into batches by texture and use of lightmapping
9970 for (i = 0;i < numsurfaces;i = j)
9973 // texture is the base texture pointer, rsurface.texture is the
9974 // current frame/skin the texture is directing us to use (for example
9975 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9976 // use skin 1 instead)
9977 texture = surfacelist[i]->texture;
9978 rsurface.texture = R_GetCurrentTexture(texture);
9979 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9981 // if this texture is not the kind we want, skip ahead to the next one
9982 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9986 if(FAKELIGHT_ENABLED || depthonly || prepass)
9988 rsurface.lightmaptexture = NULL;
9989 rsurface.deluxemaptexture = NULL;
9990 rsurface.uselightmaptexture = false;
9991 // simply scan ahead until we find a different texture or lightmap state
9992 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9997 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
9998 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
9999 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10000 // simply scan ahead until we find a different texture or lightmap state
10001 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10004 // render the range of surfaces
10005 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10007 R_FrameData_ReturnToMark();
10010 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10014 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10017 if (!rsurface.texture->currentnumlayers)
10019 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10020 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10022 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10024 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10025 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10026 else if (!rsurface.texture->currentnumlayers)
10028 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10030 // in the deferred case, transparent surfaces were queued during prepass
10031 if (!r_shadow_usingdeferredprepass)
10032 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10036 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10037 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10042 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10045 texture_t *texture;
10046 R_FrameData_SetMark();
10047 // break the surface list down into batches by texture and use of lightmapping
10048 for (i = 0;i < numsurfaces;i = j)
10051 // texture is the base texture pointer, rsurface.texture is the
10052 // current frame/skin the texture is directing us to use (for example
10053 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10054 // use skin 1 instead)
10055 texture = surfacelist[i]->texture;
10056 rsurface.texture = R_GetCurrentTexture(texture);
10057 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10059 // if this texture is not the kind we want, skip ahead to the next one
10060 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10064 if(FAKELIGHT_ENABLED || depthonly || prepass)
10066 rsurface.lightmaptexture = NULL;
10067 rsurface.deluxemaptexture = NULL;
10068 rsurface.uselightmaptexture = false;
10069 // simply scan ahead until we find a different texture or lightmap state
10070 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10075 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10076 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10077 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10078 // simply scan ahead until we find a different texture or lightmap state
10079 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10082 // render the range of surfaces
10083 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10085 R_FrameData_ReturnToMark();
10088 float locboxvertex3f[6*4*3] =
10090 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10091 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10092 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10093 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10094 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10095 1,0,0, 0,0,0, 0,1,0, 1,1,0
10098 unsigned short locboxelements[6*2*3] =
10103 12,13,14, 12,14,15,
10104 16,17,18, 16,18,19,
10108 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10111 cl_locnode_t *loc = (cl_locnode_t *)ent;
10113 float vertex3f[6*4*3];
10115 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10116 GL_DepthMask(false);
10117 GL_DepthRange(0, 1);
10118 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10119 GL_DepthTest(true);
10120 GL_CullFace(GL_NONE);
10121 R_EntityMatrix(&identitymatrix);
10123 // R_Mesh_ResetTextureState();
10125 i = surfacelist[0];
10126 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10127 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10128 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10129 surfacelist[0] < 0 ? 0.5f : 0.125f);
10131 if (VectorCompare(loc->mins, loc->maxs))
10133 VectorSet(size, 2, 2, 2);
10134 VectorMA(loc->mins, -0.5f, size, mins);
10138 VectorCopy(loc->mins, mins);
10139 VectorSubtract(loc->maxs, loc->mins, size);
10142 for (i = 0;i < 6*4*3;)
10143 for (j = 0;j < 3;j++, i++)
10144 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10146 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10147 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10148 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10151 void R_DrawLocs(void)
10154 cl_locnode_t *loc, *nearestloc;
10156 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10157 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10159 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10160 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10164 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10166 if (decalsystem->decals)
10167 Mem_Free(decalsystem->decals);
10168 memset(decalsystem, 0, sizeof(*decalsystem));
10171 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)
10174 tridecal_t *decals;
10177 // expand or initialize the system
10178 if (decalsystem->maxdecals <= decalsystem->numdecals)
10180 decalsystem_t old = *decalsystem;
10181 qboolean useshortelements;
10182 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10183 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10184 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)));
10185 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10186 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10187 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10188 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10189 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10190 if (decalsystem->numdecals)
10191 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10193 Mem_Free(old.decals);
10194 for (i = 0;i < decalsystem->maxdecals*3;i++)
10195 decalsystem->element3i[i] = i;
10196 if (useshortelements)
10197 for (i = 0;i < decalsystem->maxdecals*3;i++)
10198 decalsystem->element3s[i] = i;
10201 // grab a decal and search for another free slot for the next one
10202 decals = decalsystem->decals;
10203 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10204 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10206 decalsystem->freedecal = i;
10207 if (decalsystem->numdecals <= i)
10208 decalsystem->numdecals = i + 1;
10210 // initialize the decal
10212 decal->triangleindex = triangleindex;
10213 decal->surfaceindex = surfaceindex;
10214 decal->decalsequence = decalsequence;
10215 decal->color4f[0][0] = c0[0];
10216 decal->color4f[0][1] = c0[1];
10217 decal->color4f[0][2] = c0[2];
10218 decal->color4f[0][3] = 1;
10219 decal->color4f[1][0] = c1[0];
10220 decal->color4f[1][1] = c1[1];
10221 decal->color4f[1][2] = c1[2];
10222 decal->color4f[1][3] = 1;
10223 decal->color4f[2][0] = c2[0];
10224 decal->color4f[2][1] = c2[1];
10225 decal->color4f[2][2] = c2[2];
10226 decal->color4f[2][3] = 1;
10227 decal->vertex3f[0][0] = v0[0];
10228 decal->vertex3f[0][1] = v0[1];
10229 decal->vertex3f[0][2] = v0[2];
10230 decal->vertex3f[1][0] = v1[0];
10231 decal->vertex3f[1][1] = v1[1];
10232 decal->vertex3f[1][2] = v1[2];
10233 decal->vertex3f[2][0] = v2[0];
10234 decal->vertex3f[2][1] = v2[1];
10235 decal->vertex3f[2][2] = v2[2];
10236 decal->texcoord2f[0][0] = t0[0];
10237 decal->texcoord2f[0][1] = t0[1];
10238 decal->texcoord2f[1][0] = t1[0];
10239 decal->texcoord2f[1][1] = t1[1];
10240 decal->texcoord2f[2][0] = t2[0];
10241 decal->texcoord2f[2][1] = t2[1];
10244 extern cvar_t cl_decals_bias;
10245 extern cvar_t cl_decals_models;
10246 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10247 // baseparms, parms, temps
10248 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 const float *vertex3f;
10254 const float *normal3f;
10256 float points[2][9][3];
10263 e = rsurface.modelelement3i + 3*triangleindex;
10265 vertex3f = rsurface.modelvertex3f;
10266 normal3f = rsurface.modelnormal3f;
10268 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10270 index = 3*e[cornerindex];
10271 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10274 //TriangleNormal(v[0], v[1], v[2], normal);
10275 //if (DotProduct(normal, localnormal) < 0.0f)
10277 // clip by each of the box planes formed from the projection matrix
10278 // if anything survives, we emit the decal
10279 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]);
10282 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]);
10285 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]);
10288 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]);
10291 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]);
10294 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]);
10297 // some part of the triangle survived, so we have to accept it...
10300 // dynamic always uses the original triangle
10302 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10304 index = 3*e[cornerindex];
10305 VectorCopy(vertex3f + index, v[cornerindex]);
10308 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10310 // convert vertex positions to texcoords
10311 Matrix4x4_Transform(projection, v[cornerindex], temp);
10312 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10313 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10314 // calculate distance fade from the projection origin
10315 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10316 f = bound(0.0f, f, 1.0f);
10317 c[cornerindex][0] = r * f;
10318 c[cornerindex][1] = g * f;
10319 c[cornerindex][2] = b * f;
10320 c[cornerindex][3] = 1.0f;
10321 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10324 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence);
10326 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10327 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence);
10329 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
10331 matrix4x4_t projection;
10332 decalsystem_t *decalsystem;
10335 const msurface_t *surface;
10336 const msurface_t *surfaces;
10337 const int *surfacelist;
10338 const texture_t *texture;
10340 int numsurfacelist;
10341 int surfacelistindex;
10344 float localorigin[3];
10345 float localnormal[3];
10346 float localmins[3];
10347 float localmaxs[3];
10350 float planes[6][4];
10353 int bih_triangles_count;
10354 int bih_triangles[256];
10355 int bih_surfaces[256];
10357 decalsystem = &ent->decalsystem;
10358 model = ent->model;
10359 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10361 R_DecalSystem_Reset(&ent->decalsystem);
10365 if (!model->brush.data_leafs && !cl_decals_models.integer)
10367 if (decalsystem->model)
10368 R_DecalSystem_Reset(decalsystem);
10372 if (decalsystem->model != model)
10373 R_DecalSystem_Reset(decalsystem);
10374 decalsystem->model = model;
10376 RSurf_ActiveModelEntity(ent, true, false, false);
10378 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10379 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10380 VectorNormalize(localnormal);
10381 localsize = worldsize*rsurface.inversematrixscale;
10382 localmins[0] = localorigin[0] - localsize;
10383 localmins[1] = localorigin[1] - localsize;
10384 localmins[2] = localorigin[2] - localsize;
10385 localmaxs[0] = localorigin[0] + localsize;
10386 localmaxs[1] = localorigin[1] + localsize;
10387 localmaxs[2] = localorigin[2] + localsize;
10389 //VectorCopy(localnormal, planes[4]);
10390 //VectorVectors(planes[4], planes[2], planes[0]);
10391 AnglesFromVectors(angles, localnormal, NULL, false);
10392 AngleVectors(angles, planes[0], planes[2], planes[4]);
10393 VectorNegate(planes[0], planes[1]);
10394 VectorNegate(planes[2], planes[3]);
10395 VectorNegate(planes[4], planes[5]);
10396 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10397 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10398 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10399 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10400 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10401 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10406 matrix4x4_t forwardprojection;
10407 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10408 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10413 float projectionvector[4][3];
10414 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10415 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10416 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10417 projectionvector[0][0] = planes[0][0] * ilocalsize;
10418 projectionvector[0][1] = planes[1][0] * ilocalsize;
10419 projectionvector[0][2] = planes[2][0] * ilocalsize;
10420 projectionvector[1][0] = planes[0][1] * ilocalsize;
10421 projectionvector[1][1] = planes[1][1] * ilocalsize;
10422 projectionvector[1][2] = planes[2][1] * ilocalsize;
10423 projectionvector[2][0] = planes[0][2] * ilocalsize;
10424 projectionvector[2][1] = planes[1][2] * ilocalsize;
10425 projectionvector[2][2] = planes[2][2] * ilocalsize;
10426 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10427 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10428 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10429 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10433 dynamic = model->surfmesh.isanimated;
10434 numsurfacelist = model->nummodelsurfaces;
10435 surfacelist = model->sortedmodelsurfaces;
10436 surfaces = model->data_surfaces;
10439 bih_triangles_count = -1;
10442 if(model->render_bih.numleafs)
10443 bih = &model->render_bih;
10444 else if(model->collision_bih.numleafs)
10445 bih = &model->collision_bih;
10448 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10449 if(bih_triangles_count == 0)
10451 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10453 if(bih_triangles_count > 0)
10455 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10457 surfaceindex = bih_surfaces[triangleindex];
10458 surface = surfaces + surfaceindex;
10459 texture = surface->texture;
10460 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10462 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10464 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10469 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10471 surfaceindex = surfacelist[surfacelistindex];
10472 surface = surfaces + surfaceindex;
10473 // check cull box first because it rejects more than any other check
10474 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10476 // skip transparent surfaces
10477 texture = surface->texture;
10478 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10480 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10482 numtriangles = surface->num_triangles;
10483 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10484 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10489 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10490 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
10492 int renderentityindex;
10493 float worldmins[3];
10494 float worldmaxs[3];
10495 entity_render_t *ent;
10497 if (!cl_decals_newsystem.integer)
10500 worldmins[0] = worldorigin[0] - worldsize;
10501 worldmins[1] = worldorigin[1] - worldsize;
10502 worldmins[2] = worldorigin[2] - worldsize;
10503 worldmaxs[0] = worldorigin[0] + worldsize;
10504 worldmaxs[1] = worldorigin[1] + worldsize;
10505 worldmaxs[2] = worldorigin[2] + worldsize;
10507 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10509 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10511 ent = r_refdef.scene.entities[renderentityindex];
10512 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10515 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10519 typedef struct r_decalsystem_splatqueue_s
10521 vec3_t worldorigin;
10522 vec3_t worldnormal;
10528 r_decalsystem_splatqueue_t;
10530 int r_decalsystem_numqueued = 0;
10531 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10533 void R_DecalSystem_SplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
10535 r_decalsystem_splatqueue_t *queue;
10537 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10540 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10541 VectorCopy(worldorigin, queue->worldorigin);
10542 VectorCopy(worldnormal, queue->worldnormal);
10543 Vector4Set(queue->color, r, g, b, a);
10544 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10545 queue->worldsize = worldsize;
10546 queue->decalsequence = cl.decalsequence++;
10549 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10552 r_decalsystem_splatqueue_t *queue;
10554 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10555 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);
10556 r_decalsystem_numqueued = 0;
10559 extern cvar_t cl_decals_max;
10560 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10563 decalsystem_t *decalsystem = &ent->decalsystem;
10570 if (!decalsystem->numdecals)
10573 if (r_showsurfaces.integer)
10576 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10578 R_DecalSystem_Reset(decalsystem);
10582 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10583 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10585 if (decalsystem->lastupdatetime)
10586 frametime = (cl.time - decalsystem->lastupdatetime);
10589 decalsystem->lastupdatetime = cl.time;
10590 decal = decalsystem->decals;
10591 numdecals = decalsystem->numdecals;
10593 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10595 if (decal->color4f[0][3])
10597 decal->lived += frametime;
10598 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10600 memset(decal, 0, sizeof(*decal));
10601 if (decalsystem->freedecal > i)
10602 decalsystem->freedecal = i;
10606 decal = decalsystem->decals;
10607 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10610 // collapse the array by shuffling the tail decals into the gaps
10613 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10614 decalsystem->freedecal++;
10615 if (decalsystem->freedecal == numdecals)
10617 decal[decalsystem->freedecal] = decal[--numdecals];
10620 decalsystem->numdecals = numdecals;
10622 if (numdecals <= 0)
10624 // if there are no decals left, reset decalsystem
10625 R_DecalSystem_Reset(decalsystem);
10629 extern skinframe_t *decalskinframe;
10630 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10633 decalsystem_t *decalsystem = &ent->decalsystem;
10642 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10645 numdecals = decalsystem->numdecals;
10649 if (r_showsurfaces.integer)
10652 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10654 R_DecalSystem_Reset(decalsystem);
10658 // if the model is static it doesn't matter what value we give for
10659 // wantnormals and wanttangents, so this logic uses only rules applicable
10660 // to a model, knowing that they are meaningless otherwise
10661 if (ent == r_refdef.scene.worldentity)
10662 RSurf_ActiveWorldEntity();
10664 RSurf_ActiveModelEntity(ent, false, false, false);
10666 decalsystem->lastupdatetime = cl.time;
10667 decal = decalsystem->decals;
10669 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10671 // update vertex positions for animated models
10672 v3f = decalsystem->vertex3f;
10673 c4f = decalsystem->color4f;
10674 t2f = decalsystem->texcoord2f;
10675 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10677 if (!decal->color4f[0][3])
10680 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10683 // update color values for fading decals
10684 if (decal->lived >= cl_decals_time.value)
10685 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10689 c4f[ 0] = decal->color4f[0][0] * alpha;
10690 c4f[ 1] = decal->color4f[0][1] * alpha;
10691 c4f[ 2] = decal->color4f[0][2] * alpha;
10693 c4f[ 4] = decal->color4f[1][0] * alpha;
10694 c4f[ 5] = decal->color4f[1][1] * alpha;
10695 c4f[ 6] = decal->color4f[1][2] * alpha;
10697 c4f[ 8] = decal->color4f[2][0] * alpha;
10698 c4f[ 9] = decal->color4f[2][1] * alpha;
10699 c4f[10] = decal->color4f[2][2] * alpha;
10702 t2f[0] = decal->texcoord2f[0][0];
10703 t2f[1] = decal->texcoord2f[0][1];
10704 t2f[2] = decal->texcoord2f[1][0];
10705 t2f[3] = decal->texcoord2f[1][1];
10706 t2f[4] = decal->texcoord2f[2][0];
10707 t2f[5] = decal->texcoord2f[2][1];
10709 // update vertex positions for animated models
10710 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10712 e = rsurface.modelelement3i + 3*decal->triangleindex;
10713 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10714 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10715 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10719 VectorCopy(decal->vertex3f[0], v3f);
10720 VectorCopy(decal->vertex3f[1], v3f + 3);
10721 VectorCopy(decal->vertex3f[2], v3f + 6);
10724 if (r_refdef.fogenabled)
10726 alpha = RSurf_FogVertex(v3f);
10727 VectorScale(c4f, alpha, c4f);
10728 alpha = RSurf_FogVertex(v3f + 3);
10729 VectorScale(c4f + 4, alpha, c4f + 4);
10730 alpha = RSurf_FogVertex(v3f + 6);
10731 VectorScale(c4f + 8, alpha, c4f + 8);
10742 r_refdef.stats.drawndecals += numtris;
10744 // now render the decals all at once
10745 // (this assumes they all use one particle font texture!)
10746 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);
10747 // R_Mesh_ResetTextureState();
10748 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10749 GL_DepthMask(false);
10750 GL_DepthRange(0, 1);
10751 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10752 GL_DepthTest(true);
10753 GL_CullFace(GL_NONE);
10754 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10755 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10756 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10760 static void R_DrawModelDecals(void)
10764 // fade faster when there are too many decals
10765 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10766 for (i = 0;i < r_refdef.scene.numentities;i++)
10767 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10769 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10770 for (i = 0;i < r_refdef.scene.numentities;i++)
10771 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10772 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10774 R_DecalSystem_ApplySplatEntitiesQueue();
10776 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10777 for (i = 0;i < r_refdef.scene.numentities;i++)
10778 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10780 r_refdef.stats.totaldecals += numdecals;
10782 if (r_showsurfaces.integer)
10785 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10787 for (i = 0;i < r_refdef.scene.numentities;i++)
10789 if (!r_refdef.viewcache.entityvisible[i])
10791 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10792 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10796 extern cvar_t mod_collision_bih;
10797 void R_DrawDebugModel(void)
10799 entity_render_t *ent = rsurface.entity;
10800 int i, j, k, l, flagsmask;
10801 const msurface_t *surface;
10802 dp_model_t *model = ent->model;
10805 switch(vid.renderpath)
10807 case RENDERPATH_GL11:
10808 case RENDERPATH_GL13:
10809 case RENDERPATH_GL20:
10811 case RENDERPATH_D3D9:
10812 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10814 case RENDERPATH_D3D10:
10815 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10817 case RENDERPATH_D3D11:
10818 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10820 case RENDERPATH_SOFT:
10821 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10823 case RENDERPATH_GLES2:
10824 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10828 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10830 // R_Mesh_ResetTextureState();
10831 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10832 GL_DepthRange(0, 1);
10833 GL_DepthTest(!r_showdisabledepthtest.integer);
10834 GL_DepthMask(false);
10835 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10837 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10841 qboolean cullbox = ent == r_refdef.scene.worldentity;
10842 const q3mbrush_t *brush;
10843 const bih_t *bih = &model->collision_bih;
10844 const bih_leaf_t *bihleaf;
10845 float vertex3f[3][3];
10846 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10848 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10850 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10852 switch (bihleaf->type)
10855 brush = model->brush.data_brushes + bihleaf->itemindex;
10856 if (brush->colbrushf && brush->colbrushf->numtriangles)
10858 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);
10859 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10860 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10863 case BIH_COLLISIONTRIANGLE:
10864 triangleindex = bihleaf->itemindex;
10865 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10866 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10867 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10868 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);
10869 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10870 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10872 case BIH_RENDERTRIANGLE:
10873 triangleindex = bihleaf->itemindex;
10874 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10875 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10876 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10877 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);
10878 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10879 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10885 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10887 if (r_showtris.integer || (r_shownormals.value != 0))
10889 if (r_showdisabledepthtest.integer)
10891 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10892 GL_DepthMask(false);
10896 GL_BlendFunc(GL_ONE, GL_ZERO);
10897 GL_DepthMask(true);
10899 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10901 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10903 rsurface.texture = R_GetCurrentTexture(surface->texture);
10904 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10906 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10907 if (r_showtris.value > 0)
10909 if (!rsurface.texture->currentlayers->depthmask)
10910 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10911 else if (ent == r_refdef.scene.worldentity)
10912 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10914 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10915 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10916 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10918 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10921 if (r_shownormals.value < 0)
10923 qglBegin(GL_LINES);
10924 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10926 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10927 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10928 qglVertex3f(v[0], v[1], v[2]);
10929 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10930 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10931 qglVertex3f(v[0], v[1], v[2]);
10936 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10938 qglBegin(GL_LINES);
10939 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10941 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10942 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10943 qglVertex3f(v[0], v[1], v[2]);
10944 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10945 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10946 qglVertex3f(v[0], v[1], v[2]);
10950 qglBegin(GL_LINES);
10951 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10953 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10954 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10955 qglVertex3f(v[0], v[1], v[2]);
10956 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10957 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10958 qglVertex3f(v[0], v[1], v[2]);
10962 qglBegin(GL_LINES);
10963 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10965 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10966 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10967 qglVertex3f(v[0], v[1], v[2]);
10968 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10969 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10970 qglVertex3f(v[0], v[1], v[2]);
10977 rsurface.texture = NULL;
10981 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10982 int r_maxsurfacelist = 0;
10983 const msurface_t **r_surfacelist = NULL;
10984 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10986 int i, j, endj, flagsmask;
10987 dp_model_t *model = r_refdef.scene.worldmodel;
10988 msurface_t *surfaces;
10989 unsigned char *update;
10990 int numsurfacelist = 0;
10994 if (r_maxsurfacelist < model->num_surfaces)
10996 r_maxsurfacelist = model->num_surfaces;
10998 Mem_Free((msurface_t**)r_surfacelist);
10999 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11002 RSurf_ActiveWorldEntity();
11004 surfaces = model->data_surfaces;
11005 update = model->brushq1.lightmapupdateflags;
11007 // update light styles on this submodel
11008 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11010 model_brush_lightstyleinfo_t *style;
11011 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11013 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11015 int *list = style->surfacelist;
11016 style->value = r_refdef.scene.lightstylevalue[style->style];
11017 for (j = 0;j < style->numsurfaces;j++)
11018 update[list[j]] = true;
11023 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11027 R_DrawDebugModel();
11028 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11032 rsurface.lightmaptexture = NULL;
11033 rsurface.deluxemaptexture = NULL;
11034 rsurface.uselightmaptexture = false;
11035 rsurface.texture = NULL;
11036 rsurface.rtlight = NULL;
11037 numsurfacelist = 0;
11038 // add visible surfaces to draw list
11039 for (i = 0;i < model->nummodelsurfaces;i++)
11041 j = model->sortedmodelsurfaces[i];
11042 if (r_refdef.viewcache.world_surfacevisible[j])
11043 r_surfacelist[numsurfacelist++] = surfaces + j;
11045 // update lightmaps if needed
11046 if (model->brushq1.firstrender)
11048 model->brushq1.firstrender = false;
11049 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11051 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11055 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11056 if (r_refdef.viewcache.world_surfacevisible[j])
11058 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11060 // don't do anything if there were no surfaces
11061 if (!numsurfacelist)
11063 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11066 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11068 // add to stats if desired
11069 if (r_speeds.integer && !skysurfaces && !depthonly)
11071 r_refdef.stats.world_surfaces += numsurfacelist;
11072 for (j = 0;j < numsurfacelist;j++)
11073 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11076 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11079 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11081 int i, j, endj, flagsmask;
11082 dp_model_t *model = ent->model;
11083 msurface_t *surfaces;
11084 unsigned char *update;
11085 int numsurfacelist = 0;
11089 if (r_maxsurfacelist < model->num_surfaces)
11091 r_maxsurfacelist = model->num_surfaces;
11093 Mem_Free((msurface_t **)r_surfacelist);
11094 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11097 // if the model is static it doesn't matter what value we give for
11098 // wantnormals and wanttangents, so this logic uses only rules applicable
11099 // to a model, knowing that they are meaningless otherwise
11100 if (ent == r_refdef.scene.worldentity)
11101 RSurf_ActiveWorldEntity();
11102 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11103 RSurf_ActiveModelEntity(ent, false, false, false);
11105 RSurf_ActiveModelEntity(ent, true, true, true);
11106 else if (depthonly)
11108 switch (vid.renderpath)
11110 case RENDERPATH_GL20:
11111 case RENDERPATH_D3D9:
11112 case RENDERPATH_D3D10:
11113 case RENDERPATH_D3D11:
11114 case RENDERPATH_SOFT:
11115 case RENDERPATH_GLES2:
11116 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11118 case RENDERPATH_GL13:
11119 case RENDERPATH_GL11:
11120 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11126 switch (vid.renderpath)
11128 case RENDERPATH_GL20:
11129 case RENDERPATH_D3D9:
11130 case RENDERPATH_D3D10:
11131 case RENDERPATH_D3D11:
11132 case RENDERPATH_SOFT:
11133 case RENDERPATH_GLES2:
11134 RSurf_ActiveModelEntity(ent, true, true, false);
11136 case RENDERPATH_GL13:
11137 case RENDERPATH_GL11:
11138 RSurf_ActiveModelEntity(ent, true, false, false);
11143 surfaces = model->data_surfaces;
11144 update = model->brushq1.lightmapupdateflags;
11146 // update light styles
11147 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11149 model_brush_lightstyleinfo_t *style;
11150 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11152 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11154 int *list = style->surfacelist;
11155 style->value = r_refdef.scene.lightstylevalue[style->style];
11156 for (j = 0;j < style->numsurfaces;j++)
11157 update[list[j]] = true;
11162 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11166 R_DrawDebugModel();
11167 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11171 rsurface.lightmaptexture = NULL;
11172 rsurface.deluxemaptexture = NULL;
11173 rsurface.uselightmaptexture = false;
11174 rsurface.texture = NULL;
11175 rsurface.rtlight = NULL;
11176 numsurfacelist = 0;
11177 // add visible surfaces to draw list
11178 for (i = 0;i < model->nummodelsurfaces;i++)
11179 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11180 // don't do anything if there were no surfaces
11181 if (!numsurfacelist)
11183 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11186 // update lightmaps if needed
11190 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11195 R_BuildLightMap(ent, surfaces + j);
11200 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11202 R_BuildLightMap(ent, surfaces + j);
11203 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11205 // add to stats if desired
11206 if (r_speeds.integer && !skysurfaces && !depthonly)
11208 r_refdef.stats.entities_surfaces += numsurfacelist;
11209 for (j = 0;j < numsurfacelist;j++)
11210 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11213 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11216 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11218 static texture_t texture;
11219 static msurface_t surface;
11220 const msurface_t *surfacelist = &surface;
11222 // fake enough texture and surface state to render this geometry
11224 texture.update_lastrenderframe = -1; // regenerate this texture
11225 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11226 texture.currentskinframe = skinframe;
11227 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11228 texture.offsetmapping = OFFSETMAPPING_OFF;
11229 texture.offsetscale = 1;
11230 texture.specularscalemod = 1;
11231 texture.specularpowermod = 1;
11233 surface.texture = &texture;
11234 surface.num_triangles = numtriangles;
11235 surface.num_firsttriangle = firsttriangle;
11236 surface.num_vertices = numvertices;
11237 surface.num_firstvertex = firstvertex;
11240 rsurface.texture = R_GetCurrentTexture(surface.texture);
11241 rsurface.lightmaptexture = NULL;
11242 rsurface.deluxemaptexture = NULL;
11243 rsurface.uselightmaptexture = false;
11244 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11247 void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11249 static msurface_t surface;
11250 const msurface_t *surfacelist = &surface;
11252 // fake enough texture and surface state to render this geometry
11253 surface.texture = texture;
11254 surface.num_triangles = numtriangles;
11255 surface.num_firsttriangle = firsttriangle;
11256 surface.num_vertices = numvertices;
11257 surface.num_firstvertex = firstvertex;
11260 rsurface.texture = R_GetCurrentTexture(surface.texture);
11261 rsurface.lightmaptexture = NULL;
11262 rsurface.deluxemaptexture = NULL;
11263 rsurface.uselightmaptexture = false;
11264 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);