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 // the first pretext is which type of shader to compile as
984 // (later these will all be bound together as a program object)
985 if(qglBindFragDataLocation && (permutation & SHADERPERMUTATION_OFFSETMAPPING)) // we use textureGrad() which is glsl 1.30
987 vertstrings_list[vertstrings_count++] = "#version 130\n";
988 geomstrings_list[geomstrings_count++] = "#version 130\n";
989 fragstrings_list[fragstrings_count++] = "#version 130\n";
992 // the first pretext is which type of shader to compile as
993 // (later these will all be bound together as a program object)
994 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
995 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
996 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
998 // the second pretext is the mode (for example a light source)
999 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1000 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1001 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1002 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1004 // now add all the permutation pretexts
1005 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1007 if (permutation & (1<<i))
1009 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1010 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1011 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1012 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1016 // keep line numbers correct
1017 vertstrings_list[vertstrings_count++] = "\n";
1018 geomstrings_list[geomstrings_count++] = "\n";
1019 fragstrings_list[fragstrings_count++] = "\n";
1024 R_CompileShader_AddStaticParms(mode, permutation);
1025 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1026 vertstrings_count += shaderstaticparms_count;
1027 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1028 geomstrings_count += shaderstaticparms_count;
1029 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1030 fragstrings_count += shaderstaticparms_count;
1032 // now append the shader text itself
1033 vertstrings_list[vertstrings_count++] = vertexstring;
1034 geomstrings_list[geomstrings_count++] = geometrystring;
1035 fragstrings_list[fragstrings_count++] = fragmentstring;
1037 // if any sources were NULL, clear the respective list
1039 vertstrings_count = 0;
1040 if (!geometrystring)
1041 geomstrings_count = 0;
1042 if (!fragmentstring)
1043 fragstrings_count = 0;
1045 // compile the shader program
1046 if (vertstrings_count + geomstrings_count + fragstrings_count)
1047 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1051 qglUseProgram(p->program);CHECKGLERROR
1052 // look up all the uniform variable names we care about, so we don't
1053 // have to look them up every time we set them
1055 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1056 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1057 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1058 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1059 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1060 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1061 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1062 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1063 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1064 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1065 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1066 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1067 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1068 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1069 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1070 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1071 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1072 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1073 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1074 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1075 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1076 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1077 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1078 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1079 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1080 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1081 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1082 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1083 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1084 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1085 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1086 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1087 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1088 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1089 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1090 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1091 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1092 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1093 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1094 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1095 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1096 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1097 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1098 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1099 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1100 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1101 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1102 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1103 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1104 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1105 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1106 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1107 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1108 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1109 p->loc_OffsetMapping_Scale = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
1110 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1111 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1112 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1113 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1114 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1115 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1116 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1117 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1118 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1119 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1120 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1121 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1122 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1123 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1124 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1125 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1126 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1127 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1128 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1129 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1130 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1131 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1132 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1133 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1134 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1135 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1136 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1137 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1138 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1139 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1140 // initialize the samplers to refer to the texture units we use
1141 p->tex_Texture_First = -1;
1142 p->tex_Texture_Second = -1;
1143 p->tex_Texture_GammaRamps = -1;
1144 p->tex_Texture_Normal = -1;
1145 p->tex_Texture_Color = -1;
1146 p->tex_Texture_Gloss = -1;
1147 p->tex_Texture_Glow = -1;
1148 p->tex_Texture_SecondaryNormal = -1;
1149 p->tex_Texture_SecondaryColor = -1;
1150 p->tex_Texture_SecondaryGloss = -1;
1151 p->tex_Texture_SecondaryGlow = -1;
1152 p->tex_Texture_Pants = -1;
1153 p->tex_Texture_Shirt = -1;
1154 p->tex_Texture_FogHeightTexture = -1;
1155 p->tex_Texture_FogMask = -1;
1156 p->tex_Texture_Lightmap = -1;
1157 p->tex_Texture_Deluxemap = -1;
1158 p->tex_Texture_Attenuation = -1;
1159 p->tex_Texture_Cube = -1;
1160 p->tex_Texture_Refraction = -1;
1161 p->tex_Texture_Reflection = -1;
1162 p->tex_Texture_ShadowMap2D = -1;
1163 p->tex_Texture_CubeProjection = -1;
1164 p->tex_Texture_ScreenDepth = -1;
1165 p->tex_Texture_ScreenNormalMap = -1;
1166 p->tex_Texture_ScreenDiffuse = -1;
1167 p->tex_Texture_ScreenSpecular = -1;
1168 p->tex_Texture_ReflectMask = -1;
1169 p->tex_Texture_ReflectCube = -1;
1170 p->tex_Texture_BounceGrid = -1;
1172 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1173 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1174 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1175 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1176 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1177 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1178 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1179 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1180 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1181 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1182 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1183 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1184 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1185 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1186 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1187 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1188 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1189 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1190 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1191 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1192 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1193 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1194 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1195 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1196 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1197 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1198 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1199 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1200 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1201 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1203 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1206 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1210 Mem_Free(vertexstring);
1212 Mem_Free(geometrystring);
1214 Mem_Free(fragmentstring);
1217 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1219 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1220 if (r_glsl_permutation != perm)
1222 r_glsl_permutation = perm;
1223 if (!r_glsl_permutation->program)
1225 if (!r_glsl_permutation->compiled)
1226 R_GLSL_CompilePermutation(perm, mode, permutation);
1227 if (!r_glsl_permutation->program)
1229 // remove features until we find a valid permutation
1231 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1233 // reduce i more quickly whenever it would not remove any bits
1234 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1235 if (!(permutation & j))
1238 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1239 if (!r_glsl_permutation->compiled)
1240 R_GLSL_CompilePermutation(perm, mode, permutation);
1241 if (r_glsl_permutation->program)
1244 if (i >= SHADERPERMUTATION_COUNT)
1246 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1247 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1248 qglUseProgram(0);CHECKGLERROR
1249 return; // no bit left to clear, entire mode is broken
1254 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1256 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1257 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1258 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1265 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1266 extern D3DCAPS9 vid_d3d9caps;
1269 struct r_hlsl_permutation_s;
1270 typedef struct r_hlsl_permutation_s
1272 /// hash lookup data
1273 struct r_hlsl_permutation_s *hashnext;
1275 unsigned int permutation;
1277 /// indicates if we have tried compiling this permutation already
1279 /// NULL if compilation failed
1280 IDirect3DVertexShader9 *vertexshader;
1281 IDirect3DPixelShader9 *pixelshader;
1283 r_hlsl_permutation_t;
1285 typedef enum D3DVSREGISTER_e
1287 D3DVSREGISTER_TexMatrix = 0, // float4x4
1288 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1289 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1290 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1291 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1292 D3DVSREGISTER_ModelToLight = 20, // float4x4
1293 D3DVSREGISTER_EyePosition = 24,
1294 D3DVSREGISTER_FogPlane = 25,
1295 D3DVSREGISTER_LightDir = 26,
1296 D3DVSREGISTER_LightPosition = 27,
1300 typedef enum D3DPSREGISTER_e
1302 D3DPSREGISTER_Alpha = 0,
1303 D3DPSREGISTER_BloomBlur_Parameters = 1,
1304 D3DPSREGISTER_ClientTime = 2,
1305 D3DPSREGISTER_Color_Ambient = 3,
1306 D3DPSREGISTER_Color_Diffuse = 4,
1307 D3DPSREGISTER_Color_Specular = 5,
1308 D3DPSREGISTER_Color_Glow = 6,
1309 D3DPSREGISTER_Color_Pants = 7,
1310 D3DPSREGISTER_Color_Shirt = 8,
1311 D3DPSREGISTER_DeferredColor_Ambient = 9,
1312 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1313 D3DPSREGISTER_DeferredColor_Specular = 11,
1314 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1315 D3DPSREGISTER_DeferredMod_Specular = 13,
1316 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1317 D3DPSREGISTER_EyePosition = 15, // unused
1318 D3DPSREGISTER_FogColor = 16,
1319 D3DPSREGISTER_FogHeightFade = 17,
1320 D3DPSREGISTER_FogPlane = 18,
1321 D3DPSREGISTER_FogPlaneViewDist = 19,
1322 D3DPSREGISTER_FogRangeRecip = 20,
1323 D3DPSREGISTER_LightColor = 21,
1324 D3DPSREGISTER_LightDir = 22, // unused
1325 D3DPSREGISTER_LightPosition = 23,
1326 D3DPSREGISTER_OffsetMapping_Scale = 24,
1327 D3DPSREGISTER_PixelSize = 25,
1328 D3DPSREGISTER_ReflectColor = 26,
1329 D3DPSREGISTER_ReflectFactor = 27,
1330 D3DPSREGISTER_ReflectOffset = 28,
1331 D3DPSREGISTER_RefractColor = 29,
1332 D3DPSREGISTER_Saturation = 30,
1333 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1334 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1335 D3DPSREGISTER_ScreenToDepth = 33,
1336 D3DPSREGISTER_ShadowMap_Parameters = 34,
1337 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1338 D3DPSREGISTER_SpecularPower = 36,
1339 D3DPSREGISTER_UserVec1 = 37,
1340 D3DPSREGISTER_UserVec2 = 38,
1341 D3DPSREGISTER_UserVec3 = 39,
1342 D3DPSREGISTER_UserVec4 = 40,
1343 D3DPSREGISTER_ViewTintColor = 41,
1344 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1345 D3DPSREGISTER_BloomColorSubtract = 43,
1346 D3DPSREGISTER_ViewToLight = 44, // float4x4
1347 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1348 D3DPSREGISTER_NormalmapScrollBlend = 52,
1353 /// information about each possible shader permutation
1354 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1355 /// currently selected permutation
1356 r_hlsl_permutation_t *r_hlsl_permutation;
1357 /// storage for permutations linked in the hash table
1358 memexpandablearray_t r_hlsl_permutationarray;
1360 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1362 //unsigned int hashdepth = 0;
1363 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1364 r_hlsl_permutation_t *p;
1365 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1367 if (p->mode == mode && p->permutation == permutation)
1369 //if (hashdepth > 10)
1370 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1375 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1377 p->permutation = permutation;
1378 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1379 r_hlsl_permutationhash[mode][hashindex] = p;
1380 //if (hashdepth > 10)
1381 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1385 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1388 if (!filename || !filename[0])
1390 if (!strcmp(filename, "hlsl/default.hlsl"))
1392 if (!hlslshaderstring)
1394 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1395 if (hlslshaderstring)
1396 Con_DPrintf("Loading shaders from file %s...\n", filename);
1398 hlslshaderstring = (char *)builtinhlslshaderstring;
1400 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1401 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1402 return shaderstring;
1404 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1407 if (printfromdisknotice)
1408 Con_DPrintf("from disk %s... ", filename);
1409 return shaderstring;
1411 return shaderstring;
1415 //#include <d3dx9shader.h>
1416 //#include <d3dx9mesh.h>
1418 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1420 DWORD *vsbin = NULL;
1421 DWORD *psbin = NULL;
1422 fs_offset_t vsbinsize;
1423 fs_offset_t psbinsize;
1424 // IDirect3DVertexShader9 *vs = NULL;
1425 // IDirect3DPixelShader9 *ps = NULL;
1426 ID3DXBuffer *vslog = NULL;
1427 ID3DXBuffer *vsbuffer = NULL;
1428 ID3DXConstantTable *vsconstanttable = NULL;
1429 ID3DXBuffer *pslog = NULL;
1430 ID3DXBuffer *psbuffer = NULL;
1431 ID3DXConstantTable *psconstanttable = NULL;
1434 char temp[MAX_INPUTLINE];
1435 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1436 qboolean debugshader = gl_paranoid.integer != 0;
1437 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1438 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1441 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1442 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1444 if ((!vsbin && vertstring) || (!psbin && fragstring))
1446 const char* dllnames_d3dx9 [] =
1470 dllhandle_t d3dx9_dll = NULL;
1471 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1472 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1473 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1474 dllfunction_t d3dx9_dllfuncs[] =
1476 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1477 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1478 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1481 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1483 DWORD shaderflags = 0;
1485 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1486 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1487 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1488 if (vertstring && vertstring[0])
1492 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1493 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1494 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1495 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1498 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1501 vsbinsize = vsbuffer->GetBufferSize();
1502 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1503 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1504 vsbuffer->Release();
1508 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1509 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1513 if (fragstring && fragstring[0])
1517 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1518 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1519 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1520 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1523 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1526 psbinsize = psbuffer->GetBufferSize();
1527 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1528 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1529 psbuffer->Release();
1533 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1534 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1538 Sys_UnloadLibrary(&d3dx9_dll);
1541 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1545 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1546 if (FAILED(vsresult))
1547 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1548 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1549 if (FAILED(psresult))
1550 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1552 // free the shader data
1553 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1554 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1557 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1560 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1561 int vertstring_length = 0;
1562 int geomstring_length = 0;
1563 int fragstring_length = 0;
1565 char *vertexstring, *geometrystring, *fragmentstring;
1566 char *vertstring, *geomstring, *fragstring;
1567 char permutationname[256];
1568 char cachename[256];
1569 int vertstrings_count = 0;
1570 int geomstrings_count = 0;
1571 int fragstrings_count = 0;
1572 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1573 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1574 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1579 p->vertexshader = NULL;
1580 p->pixelshader = NULL;
1582 permutationname[0] = 0;
1584 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1585 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1586 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1588 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1589 strlcat(cachename, "hlsl/", sizeof(cachename));
1591 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1592 vertstrings_count = 0;
1593 geomstrings_count = 0;
1594 fragstrings_count = 0;
1595 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1596 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1597 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1599 // the first pretext is which type of shader to compile as
1600 // (later these will all be bound together as a program object)
1601 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1602 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1603 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1605 // the second pretext is the mode (for example a light source)
1606 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1607 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1608 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1609 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1610 strlcat(cachename, modeinfo->name, sizeof(cachename));
1612 // now add all the permutation pretexts
1613 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1615 if (permutation & (1<<i))
1617 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1618 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1619 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1620 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1621 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1625 // keep line numbers correct
1626 vertstrings_list[vertstrings_count++] = "\n";
1627 geomstrings_list[geomstrings_count++] = "\n";
1628 fragstrings_list[fragstrings_count++] = "\n";
1633 R_CompileShader_AddStaticParms(mode, permutation);
1634 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1635 vertstrings_count += shaderstaticparms_count;
1636 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1637 geomstrings_count += shaderstaticparms_count;
1638 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1639 fragstrings_count += shaderstaticparms_count;
1641 // replace spaces in the cachename with _ characters
1642 for (i = 0;cachename[i];i++)
1643 if (cachename[i] == ' ')
1646 // now append the shader text itself
1647 vertstrings_list[vertstrings_count++] = vertexstring;
1648 geomstrings_list[geomstrings_count++] = geometrystring;
1649 fragstrings_list[fragstrings_count++] = fragmentstring;
1651 // if any sources were NULL, clear the respective list
1653 vertstrings_count = 0;
1654 if (!geometrystring)
1655 geomstrings_count = 0;
1656 if (!fragmentstring)
1657 fragstrings_count = 0;
1659 vertstring_length = 0;
1660 for (i = 0;i < vertstrings_count;i++)
1661 vertstring_length += strlen(vertstrings_list[i]);
1662 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1663 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1664 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1666 geomstring_length = 0;
1667 for (i = 0;i < geomstrings_count;i++)
1668 geomstring_length += strlen(geomstrings_list[i]);
1669 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1670 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1671 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1673 fragstring_length = 0;
1674 for (i = 0;i < fragstrings_count;i++)
1675 fragstring_length += strlen(fragstrings_list[i]);
1676 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1677 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1678 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1680 // try to load the cached shader, or generate one
1681 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1683 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1684 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1686 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1690 Mem_Free(vertstring);
1692 Mem_Free(geomstring);
1694 Mem_Free(fragstring);
1696 Mem_Free(vertexstring);
1698 Mem_Free(geometrystring);
1700 Mem_Free(fragmentstring);
1703 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1704 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1705 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1706 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1707 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1708 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1710 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1711 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1712 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1713 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1714 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1715 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1717 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1719 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1720 if (r_hlsl_permutation != perm)
1722 r_hlsl_permutation = perm;
1723 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1725 if (!r_hlsl_permutation->compiled)
1726 R_HLSL_CompilePermutation(perm, mode, permutation);
1727 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1729 // remove features until we find a valid permutation
1731 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1733 // reduce i more quickly whenever it would not remove any bits
1734 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1735 if (!(permutation & j))
1738 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1739 if (!r_hlsl_permutation->compiled)
1740 R_HLSL_CompilePermutation(perm, mode, permutation);
1741 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1744 if (i >= SHADERPERMUTATION_COUNT)
1746 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1747 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1748 return; // no bit left to clear, entire mode is broken
1752 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1753 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1755 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1756 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1757 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1761 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1763 DPSOFTRAST_SetShader(mode, permutation);
1764 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1765 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1766 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1769 void R_GLSL_Restart_f(void)
1771 unsigned int i, limit;
1772 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1773 Mem_Free(glslshaderstring);
1774 glslshaderstring = NULL;
1775 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1776 Mem_Free(hlslshaderstring);
1777 hlslshaderstring = NULL;
1778 switch(vid.renderpath)
1780 case RENDERPATH_D3D9:
1783 r_hlsl_permutation_t *p;
1784 r_hlsl_permutation = NULL;
1785 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1786 for (i = 0;i < limit;i++)
1788 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1790 if (p->vertexshader)
1791 IDirect3DVertexShader9_Release(p->vertexshader);
1793 IDirect3DPixelShader9_Release(p->pixelshader);
1794 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1797 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1801 case RENDERPATH_D3D10:
1802 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1804 case RENDERPATH_D3D11:
1805 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1807 case RENDERPATH_GL20:
1808 case RENDERPATH_GLES2:
1810 r_glsl_permutation_t *p;
1811 r_glsl_permutation = NULL;
1812 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1813 for (i = 0;i < limit;i++)
1815 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1817 GL_Backend_FreeProgram(p->program);
1818 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1821 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1824 case RENDERPATH_GL13:
1825 case RENDERPATH_GL11:
1827 case RENDERPATH_SOFT:
1832 void R_GLSL_DumpShader_f(void)
1837 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1840 FS_Print(file, "/* The engine may define the following macros:\n");
1841 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1842 for (i = 0;i < SHADERMODE_COUNT;i++)
1843 FS_Print(file, glslshadermodeinfo[i].pretext);
1844 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1845 FS_Print(file, shaderpermutationinfo[i].pretext);
1846 FS_Print(file, "*/\n");
1847 FS_Print(file, builtinshaderstring);
1849 Con_Printf("glsl/default.glsl written\n");
1852 Con_Printf("failed to write to glsl/default.glsl\n");
1854 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1857 FS_Print(file, "/* The engine may define the following macros:\n");
1858 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1859 for (i = 0;i < SHADERMODE_COUNT;i++)
1860 FS_Print(file, hlslshadermodeinfo[i].pretext);
1861 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1862 FS_Print(file, shaderpermutationinfo[i].pretext);
1863 FS_Print(file, "*/\n");
1864 FS_Print(file, builtinhlslshaderstring);
1866 Con_Printf("hlsl/default.hlsl written\n");
1869 Con_Printf("failed to write to hlsl/default.hlsl\n");
1872 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1875 texturemode = GL_MODULATE;
1876 switch (vid.renderpath)
1878 case RENDERPATH_D3D9:
1880 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1881 R_Mesh_TexBind(GL20TU_FIRST , first );
1882 R_Mesh_TexBind(GL20TU_SECOND, second);
1885 case RENDERPATH_D3D10:
1886 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1888 case RENDERPATH_D3D11:
1889 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1891 case RENDERPATH_GL20:
1892 case RENDERPATH_GLES2:
1893 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1894 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1895 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1897 case RENDERPATH_GL13:
1898 R_Mesh_TexBind(0, first );
1899 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1900 R_Mesh_TexBind(1, second);
1902 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1904 case RENDERPATH_GL11:
1905 R_Mesh_TexBind(0, first );
1907 case RENDERPATH_SOFT:
1908 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1909 R_Mesh_TexBind(GL20TU_FIRST , first );
1910 R_Mesh_TexBind(GL20TU_SECOND, second);
1915 void R_SetupShader_DepthOrShadow(void)
1917 switch (vid.renderpath)
1919 case RENDERPATH_D3D9:
1921 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1924 case RENDERPATH_D3D10:
1925 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1927 case RENDERPATH_D3D11:
1928 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1930 case RENDERPATH_GL20:
1931 case RENDERPATH_GLES2:
1932 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1934 case RENDERPATH_GL13:
1935 R_Mesh_TexBind(0, 0);
1936 R_Mesh_TexBind(1, 0);
1938 case RENDERPATH_GL11:
1939 R_Mesh_TexBind(0, 0);
1941 case RENDERPATH_SOFT:
1942 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1947 void R_SetupShader_ShowDepth(void)
1949 switch (vid.renderpath)
1951 case RENDERPATH_D3D9:
1953 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1956 case RENDERPATH_D3D10:
1957 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1959 case RENDERPATH_D3D11:
1960 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1962 case RENDERPATH_GL20:
1963 case RENDERPATH_GLES2:
1964 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1966 case RENDERPATH_GL13:
1968 case RENDERPATH_GL11:
1970 case RENDERPATH_SOFT:
1971 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1976 extern qboolean r_shadow_usingdeferredprepass;
1977 extern cvar_t r_shadow_deferred_8bitrange;
1978 extern rtexture_t *r_shadow_attenuationgradienttexture;
1979 extern rtexture_t *r_shadow_attenuation2dtexture;
1980 extern rtexture_t *r_shadow_attenuation3dtexture;
1981 extern qboolean r_shadow_usingshadowmap2d;
1982 extern qboolean r_shadow_usingshadowmaportho;
1983 extern float r_shadow_shadowmap_texturescale[2];
1984 extern float r_shadow_shadowmap_parameters[4];
1985 extern qboolean r_shadow_shadowmapvsdct;
1986 extern qboolean r_shadow_shadowmapsampler;
1987 extern int r_shadow_shadowmappcf;
1988 extern rtexture_t *r_shadow_shadowmap2dtexture;
1989 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1990 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1991 extern matrix4x4_t r_shadow_shadowmapmatrix;
1992 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1993 extern int r_shadow_prepass_width;
1994 extern int r_shadow_prepass_height;
1995 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1996 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1997 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
1998 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
1999 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2001 #define BLENDFUNC_ALLOWS_COLORMOD 1
2002 #define BLENDFUNC_ALLOWS_FOG 2
2003 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2004 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2005 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2006 static int R_BlendFuncFlags(int src, int dst)
2010 // a blendfunc allows colormod if:
2011 // a) it can never keep the destination pixel invariant, or
2012 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2013 // this is to prevent unintended side effects from colormod
2015 // a blendfunc allows fog if:
2016 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2017 // this is to prevent unintended side effects from fog
2019 // these checks are the output of fogeval.pl
2021 r |= BLENDFUNC_ALLOWS_COLORMOD;
2022 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2023 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2024 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2025 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2026 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2027 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2028 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2029 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2030 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2031 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2032 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2033 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2034 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2035 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2036 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2037 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2038 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2039 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2040 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2041 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2042 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2047 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
2049 // select a permutation of the lighting shader appropriate to this
2050 // combination of texture, entity, light source, and fogging, only use the
2051 // minimum features necessary to avoid wasting rendering time in the
2052 // fragment shader on features that are not being used
2053 unsigned int permutation = 0;
2054 unsigned int mode = 0;
2056 static float dummy_colormod[3] = {1, 1, 1};
2057 float *colormod = rsurface.colormod;
2059 matrix4x4_t tempmatrix;
2060 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2061 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2062 permutation |= SHADERPERMUTATION_ALPHAKILL;
2063 if (rsurfacepass == RSURFPASS_BACKGROUND)
2065 // distorted background
2066 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2068 mode = SHADERMODE_WATER;
2069 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2070 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2071 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2073 // this is the right thing to do for wateralpha
2074 GL_BlendFunc(GL_ONE, GL_ZERO);
2075 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2079 // this is the right thing to do for entity alpha
2080 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2081 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2084 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2086 mode = SHADERMODE_REFRACTION;
2087 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2088 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2092 mode = SHADERMODE_GENERIC;
2093 permutation |= SHADERPERMUTATION_DIFFUSE;
2094 GL_BlendFunc(GL_ONE, GL_ZERO);
2095 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2098 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2100 if (r_glsl_offsetmapping.integer)
2102 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2103 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2104 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2105 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2106 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2108 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2109 if (r_glsl_offsetmapping_reliefmapping.integer)
2110 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2113 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2114 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2115 // normalmap (deferred prepass), may use alpha test on diffuse
2116 mode = SHADERMODE_DEFERREDGEOMETRY;
2117 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2118 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2119 GL_BlendFunc(GL_ONE, GL_ZERO);
2120 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2122 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2124 if (r_glsl_offsetmapping.integer)
2126 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2127 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2128 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2129 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2130 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2132 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2133 if (r_glsl_offsetmapping_reliefmapping.integer)
2134 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2137 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2138 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2140 mode = SHADERMODE_LIGHTSOURCE;
2141 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2142 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2143 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2144 permutation |= SHADERPERMUTATION_CUBEFILTER;
2145 if (diffusescale > 0)
2146 permutation |= SHADERPERMUTATION_DIFFUSE;
2147 if (specularscale > 0)
2148 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2149 if (r_refdef.fogenabled)
2150 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2151 if (rsurface.texture->colormapping)
2152 permutation |= SHADERPERMUTATION_COLORMAPPING;
2153 if (r_shadow_usingshadowmap2d)
2155 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2156 if(r_shadow_shadowmapvsdct)
2157 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2159 if (r_shadow_shadowmapsampler)
2160 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2161 if (r_shadow_shadowmappcf > 1)
2162 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2163 else if (r_shadow_shadowmappcf)
2164 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2166 if (rsurface.texture->reflectmasktexture)
2167 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2168 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2169 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2171 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2173 if (r_glsl_offsetmapping.integer)
2175 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2176 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2177 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2178 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2179 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2181 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2182 if (r_glsl_offsetmapping_reliefmapping.integer)
2183 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2186 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2187 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2188 // unshaded geometry (fullbright or ambient model lighting)
2189 mode = SHADERMODE_FLATCOLOR;
2190 ambientscale = diffusescale = specularscale = 0;
2191 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2192 permutation |= SHADERPERMUTATION_GLOW;
2193 if (r_refdef.fogenabled)
2194 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2195 if (rsurface.texture->colormapping)
2196 permutation |= SHADERPERMUTATION_COLORMAPPING;
2197 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2199 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2200 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2202 if (r_shadow_shadowmapsampler)
2203 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2204 if (r_shadow_shadowmappcf > 1)
2205 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2206 else if (r_shadow_shadowmappcf)
2207 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2209 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2210 permutation |= SHADERPERMUTATION_REFLECTION;
2211 if (rsurface.texture->reflectmasktexture)
2212 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2213 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2214 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2216 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2218 if (r_glsl_offsetmapping.integer)
2220 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2221 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2222 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2223 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2224 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2226 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2227 if (r_glsl_offsetmapping_reliefmapping.integer)
2228 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2231 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2232 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2233 // directional model lighting
2234 mode = SHADERMODE_LIGHTDIRECTION;
2235 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2236 permutation |= SHADERPERMUTATION_GLOW;
2237 permutation |= SHADERPERMUTATION_DIFFUSE;
2238 if (specularscale > 0)
2239 permutation |= SHADERPERMUTATION_SPECULAR;
2240 if (r_refdef.fogenabled)
2241 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2242 if (rsurface.texture->colormapping)
2243 permutation |= SHADERPERMUTATION_COLORMAPPING;
2244 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2246 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2247 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2249 if (r_shadow_shadowmapsampler)
2250 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2251 if (r_shadow_shadowmappcf > 1)
2252 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2253 else if (r_shadow_shadowmappcf)
2254 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2256 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2257 permutation |= SHADERPERMUTATION_REFLECTION;
2258 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2259 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2260 if (rsurface.texture->reflectmasktexture)
2261 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2262 if (r_shadow_bouncegridtexture)
2263 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2264 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2265 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2267 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2269 if (r_glsl_offsetmapping.integer)
2271 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2272 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2273 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2274 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2275 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2277 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2278 if (r_glsl_offsetmapping_reliefmapping.integer)
2279 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2282 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2283 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2284 // ambient model lighting
2285 mode = SHADERMODE_LIGHTDIRECTION;
2286 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2287 permutation |= SHADERPERMUTATION_GLOW;
2288 if (r_refdef.fogenabled)
2289 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2290 if (rsurface.texture->colormapping)
2291 permutation |= SHADERPERMUTATION_COLORMAPPING;
2292 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2294 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2295 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2297 if (r_shadow_shadowmapsampler)
2298 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2299 if (r_shadow_shadowmappcf > 1)
2300 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2301 else if (r_shadow_shadowmappcf)
2302 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2304 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2305 permutation |= SHADERPERMUTATION_REFLECTION;
2306 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2307 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2308 if (rsurface.texture->reflectmasktexture)
2309 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2310 if (r_shadow_bouncegridtexture)
2311 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2312 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2313 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2317 if (r_glsl_offsetmapping.integer)
2319 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2320 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2321 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2322 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2323 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2325 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2326 if (r_glsl_offsetmapping_reliefmapping.integer)
2327 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2330 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2331 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2333 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2334 permutation |= SHADERPERMUTATION_GLOW;
2335 if (r_refdef.fogenabled)
2336 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2337 if (rsurface.texture->colormapping)
2338 permutation |= SHADERPERMUTATION_COLORMAPPING;
2339 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2341 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2342 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2344 if (r_shadow_shadowmapsampler)
2345 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2346 if (r_shadow_shadowmappcf > 1)
2347 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2348 else if (r_shadow_shadowmappcf)
2349 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2351 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2352 permutation |= SHADERPERMUTATION_REFLECTION;
2353 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2354 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2355 if (rsurface.texture->reflectmasktexture)
2356 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2357 if (FAKELIGHT_ENABLED)
2359 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2360 mode = SHADERMODE_FAKELIGHT;
2361 permutation |= SHADERPERMUTATION_DIFFUSE;
2362 if (specularscale > 0)
2363 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2365 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2367 // deluxemapping (light direction texture)
2368 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2369 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2371 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2372 permutation |= SHADERPERMUTATION_DIFFUSE;
2373 if (specularscale > 0)
2374 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2376 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2378 // fake deluxemapping (uniform light direction in tangentspace)
2379 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2380 permutation |= SHADERPERMUTATION_DIFFUSE;
2381 if (specularscale > 0)
2382 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2384 else if (rsurface.uselightmaptexture)
2386 // ordinary lightmapping (q1bsp, q3bsp)
2387 mode = SHADERMODE_LIGHTMAP;
2391 // ordinary vertex coloring (q3bsp)
2392 mode = SHADERMODE_VERTEXCOLOR;
2394 if (r_shadow_bouncegridtexture)
2395 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2396 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2397 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2399 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2400 colormod = dummy_colormod;
2401 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2402 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2403 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2404 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2405 switch(vid.renderpath)
2407 case RENDERPATH_D3D9:
2409 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2410 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2411 R_SetupShader_SetPermutationHLSL(mode, permutation);
2412 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2413 if (mode == SHADERMODE_LIGHTSOURCE)
2415 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2416 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2420 if (mode == SHADERMODE_LIGHTDIRECTION)
2422 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2425 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2426 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2427 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2428 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2429 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2431 if (mode == SHADERMODE_LIGHTSOURCE)
2433 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2434 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2435 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2436 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2437 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2439 // additive passes are only darkened by fog, not tinted
2440 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2441 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2445 if (mode == SHADERMODE_FLATCOLOR)
2447 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2449 else if (mode == SHADERMODE_LIGHTDIRECTION)
2451 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2452 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2453 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2454 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2455 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2456 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2457 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2461 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2462 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2463 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2464 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2465 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2467 // additive passes are only darkened by fog, not tinted
2468 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2469 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2471 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2472 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2473 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2474 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2475 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2476 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2477 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2478 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2479 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2480 if (mode == SHADERMODE_WATER)
2481 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2483 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2484 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2485 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2486 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2487 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2488 if (rsurface.texture->pantstexture)
2489 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2491 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2492 if (rsurface.texture->shirttexture)
2493 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2495 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2496 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2497 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2498 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2499 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2500 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2501 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2502 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2504 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2505 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2506 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2507 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2508 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2509 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2510 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2511 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2512 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2513 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2514 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2515 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2516 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2517 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2518 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2519 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2520 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2521 if (rsurfacepass == RSURFPASS_BACKGROUND)
2523 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2524 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2525 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2529 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2531 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2532 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2533 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2534 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2535 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2537 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2538 if (rsurface.rtlight)
2540 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2541 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2546 case RENDERPATH_D3D10:
2547 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2549 case RENDERPATH_D3D11:
2550 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2552 case RENDERPATH_GL20:
2553 case RENDERPATH_GLES2:
2554 if (!vid.useinterleavedarrays)
2556 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2557 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2558 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2559 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2560 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2561 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2562 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2563 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2567 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2568 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2570 R_SetupShader_SetPermutationGLSL(mode, permutation);
2571 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2572 if (mode == SHADERMODE_LIGHTSOURCE)
2574 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2575 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2576 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2577 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2578 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2579 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2581 // additive passes are only darkened by fog, not tinted
2582 if (r_glsl_permutation->loc_FogColor >= 0)
2583 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2584 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2588 if (mode == SHADERMODE_FLATCOLOR)
2590 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2592 else if (mode == SHADERMODE_LIGHTDIRECTION)
2594 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2595 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2596 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2597 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2598 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2599 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2600 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2604 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2605 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2606 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2607 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2608 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2610 // additive passes are only darkened by fog, not tinted
2611 if (r_glsl_permutation->loc_FogColor >= 0)
2613 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2614 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2616 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2618 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2619 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2620 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2621 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2622 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2623 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2624 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2625 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2626 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2628 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2629 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2630 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2631 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2632 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2634 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2635 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2636 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2637 if (r_glsl_permutation->loc_Color_Pants >= 0)
2639 if (rsurface.texture->pantstexture)
2640 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2642 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2644 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2646 if (rsurface.texture->shirttexture)
2647 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2649 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2651 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2652 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2653 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2654 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2655 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2656 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2657 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2658 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2659 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2661 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2662 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2663 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2664 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2665 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2666 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2667 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2668 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2669 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2670 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2671 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2672 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2673 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2674 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2675 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2676 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2677 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2678 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2679 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2680 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2681 if (rsurfacepass == RSURFPASS_BACKGROUND)
2683 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2684 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2685 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2689 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2691 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2692 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2693 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2694 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2695 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2697 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2698 if (rsurface.rtlight)
2700 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2701 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2704 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2707 case RENDERPATH_GL13:
2708 case RENDERPATH_GL11:
2710 case RENDERPATH_SOFT:
2711 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2712 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2713 R_SetupShader_SetPermutationSoft(mode, permutation);
2714 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2715 if (mode == SHADERMODE_LIGHTSOURCE)
2717 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2718 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2719 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2720 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2721 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2722 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2724 // additive passes are only darkened by fog, not tinted
2725 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2726 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2730 if (mode == SHADERMODE_FLATCOLOR)
2732 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2734 else if (mode == SHADERMODE_LIGHTDIRECTION)
2736 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2737 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2738 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2739 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2740 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2741 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2742 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2746 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2747 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2748 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2749 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2750 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2752 // additive passes are only darkened by fog, not tinted
2753 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2754 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2756 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2757 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2758 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2759 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2760 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2761 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2762 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2763 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2764 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2765 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2767 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2768 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2769 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2770 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2771 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2773 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2774 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2775 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2776 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2778 if (rsurface.texture->pantstexture)
2779 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2781 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2783 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2785 if (rsurface.texture->shirttexture)
2786 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2788 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2790 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2791 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2792 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2793 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2794 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2795 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2796 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2798 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2799 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2800 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2801 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2802 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2803 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2804 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2805 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2806 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2807 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2808 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2809 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2810 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2811 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2812 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2813 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2814 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2815 if (rsurfacepass == RSURFPASS_BACKGROUND)
2817 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2818 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2819 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2823 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2825 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2826 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2827 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2828 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2829 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2831 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2832 if (rsurface.rtlight)
2834 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2835 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2842 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2844 // select a permutation of the lighting shader appropriate to this
2845 // combination of texture, entity, light source, and fogging, only use the
2846 // minimum features necessary to avoid wasting rendering time in the
2847 // fragment shader on features that are not being used
2848 unsigned int permutation = 0;
2849 unsigned int mode = 0;
2850 const float *lightcolorbase = rtlight->currentcolor;
2851 float ambientscale = rtlight->ambientscale;
2852 float diffusescale = rtlight->diffusescale;
2853 float specularscale = rtlight->specularscale;
2854 // this is the location of the light in view space
2855 vec3_t viewlightorigin;
2856 // this transforms from view space (camera) to light space (cubemap)
2857 matrix4x4_t viewtolight;
2858 matrix4x4_t lighttoview;
2859 float viewtolight16f[16];
2860 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2862 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2863 if (rtlight->currentcubemap != r_texture_whitecube)
2864 permutation |= SHADERPERMUTATION_CUBEFILTER;
2865 if (diffusescale > 0)
2866 permutation |= SHADERPERMUTATION_DIFFUSE;
2867 if (specularscale > 0)
2868 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2869 if (r_shadow_usingshadowmap2d)
2871 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2872 if (r_shadow_shadowmapvsdct)
2873 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2875 if (r_shadow_shadowmapsampler)
2876 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2877 if (r_shadow_shadowmappcf > 1)
2878 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2879 else if (r_shadow_shadowmappcf)
2880 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2882 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2883 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2884 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2885 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2886 switch(vid.renderpath)
2888 case RENDERPATH_D3D9:
2890 R_SetupShader_SetPermutationHLSL(mode, permutation);
2891 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2892 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2893 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2894 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2895 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2896 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2897 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2898 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2899 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2900 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2902 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2903 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2904 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2905 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2906 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2907 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2910 case RENDERPATH_D3D10:
2911 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2913 case RENDERPATH_D3D11:
2914 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2916 case RENDERPATH_GL20:
2917 case RENDERPATH_GLES2:
2918 R_SetupShader_SetPermutationGLSL(mode, permutation);
2919 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2920 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2921 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2922 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2923 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2924 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2925 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2926 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2927 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f( r_glsl_permutation->loc_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2928 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2930 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2931 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2932 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2933 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2934 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2935 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2937 case RENDERPATH_GL13:
2938 case RENDERPATH_GL11:
2940 case RENDERPATH_SOFT:
2941 R_SetupShader_SetPermutationGLSL(mode, permutation);
2942 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2943 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2944 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2945 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2946 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2947 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2948 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2949 DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2950 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2951 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2953 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2954 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2955 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2956 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2957 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2958 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2963 #define SKINFRAME_HASH 1024
2967 int loadsequence; // incremented each level change
2968 memexpandablearray_t array;
2969 skinframe_t *hash[SKINFRAME_HASH];
2972 r_skinframe_t r_skinframe;
2974 void R_SkinFrame_PrepareForPurge(void)
2976 r_skinframe.loadsequence++;
2977 // wrap it without hitting zero
2978 if (r_skinframe.loadsequence >= 200)
2979 r_skinframe.loadsequence = 1;
2982 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2986 // mark the skinframe as used for the purging code
2987 skinframe->loadsequence = r_skinframe.loadsequence;
2990 void R_SkinFrame_Purge(void)
2994 for (i = 0;i < SKINFRAME_HASH;i++)
2996 for (s = r_skinframe.hash[i];s;s = s->next)
2998 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3000 if (s->merged == s->base)
3002 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3003 R_PurgeTexture(s->stain );s->stain = NULL;
3004 R_PurgeTexture(s->merged);s->merged = NULL;
3005 R_PurgeTexture(s->base );s->base = NULL;
3006 R_PurgeTexture(s->pants );s->pants = NULL;
3007 R_PurgeTexture(s->shirt );s->shirt = NULL;
3008 R_PurgeTexture(s->nmap );s->nmap = NULL;
3009 R_PurgeTexture(s->gloss );s->gloss = NULL;
3010 R_PurgeTexture(s->glow );s->glow = NULL;
3011 R_PurgeTexture(s->fog );s->fog = NULL;
3012 R_PurgeTexture(s->reflect);s->reflect = NULL;
3013 s->loadsequence = 0;
3019 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3021 char basename[MAX_QPATH];
3023 Image_StripImageExtension(name, basename, sizeof(basename));
3025 if( last == NULL ) {
3027 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3028 item = r_skinframe.hash[hashindex];
3033 // linearly search through the hash bucket
3034 for( ; item ; item = item->next ) {
3035 if( !strcmp( item->basename, basename ) ) {
3042 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3046 char basename[MAX_QPATH];
3048 Image_StripImageExtension(name, basename, sizeof(basename));
3050 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3051 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3052 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3056 rtexture_t *dyntexture;
3057 // check whether its a dynamic texture
3058 dyntexture = CL_GetDynTexture( basename );
3059 if (!add && !dyntexture)
3061 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3062 memset(item, 0, sizeof(*item));
3063 strlcpy(item->basename, basename, sizeof(item->basename));
3064 item->base = dyntexture; // either NULL or dyntexture handle
3065 item->textureflags = textureflags;
3066 item->comparewidth = comparewidth;
3067 item->compareheight = compareheight;
3068 item->comparecrc = comparecrc;
3069 item->next = r_skinframe.hash[hashindex];
3070 r_skinframe.hash[hashindex] = item;
3072 else if( item->base == NULL )
3074 rtexture_t *dyntexture;
3075 // check whether its a dynamic texture
3076 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3077 dyntexture = CL_GetDynTexture( basename );
3078 item->base = dyntexture; // either NULL or dyntexture handle
3081 R_SkinFrame_MarkUsed(item);
3085 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3087 unsigned long long avgcolor[5], wsum; \
3095 for(pix = 0; pix < cnt; ++pix) \
3098 for(comp = 0; comp < 3; ++comp) \
3100 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3103 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3105 for(comp = 0; comp < 3; ++comp) \
3106 avgcolor[comp] += getpixel * w; \
3109 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3110 avgcolor[4] += getpixel; \
3112 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3114 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3115 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3116 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3117 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3120 extern cvar_t gl_picmip;
3121 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3124 unsigned char *pixels;
3125 unsigned char *bumppixels;
3126 unsigned char *basepixels = NULL;
3127 int basepixels_width = 0;
3128 int basepixels_height = 0;
3129 skinframe_t *skinframe;
3130 rtexture_t *ddsbase = NULL;
3131 qboolean ddshasalpha = false;
3132 float ddsavgcolor[4];
3133 char basename[MAX_QPATH];
3134 int miplevel = R_PicmipForFlags(textureflags);
3135 int savemiplevel = miplevel;
3138 if (cls.state == ca_dedicated)
3141 // return an existing skinframe if already loaded
3142 // if loading of the first image fails, don't make a new skinframe as it
3143 // would cause all future lookups of this to be missing
3144 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3145 if (skinframe && skinframe->base)
3148 Image_StripImageExtension(name, basename, sizeof(basename));
3150 // check for DDS texture file first
3151 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3153 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3154 if (basepixels == NULL)
3158 // FIXME handle miplevel
3160 if (developer_loading.integer)
3161 Con_Printf("loading skin \"%s\"\n", name);
3163 // we've got some pixels to store, so really allocate this new texture now
3165 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3166 skinframe->stain = NULL;
3167 skinframe->merged = NULL;
3168 skinframe->base = NULL;
3169 skinframe->pants = NULL;
3170 skinframe->shirt = NULL;
3171 skinframe->nmap = NULL;
3172 skinframe->gloss = NULL;
3173 skinframe->glow = NULL;
3174 skinframe->fog = NULL;
3175 skinframe->reflect = NULL;
3176 skinframe->hasalpha = false;
3180 skinframe->base = ddsbase;
3181 skinframe->hasalpha = ddshasalpha;
3182 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3183 if (r_loadfog && skinframe->hasalpha)
3184 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3185 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3189 basepixels_width = image_width;
3190 basepixels_height = image_height;
3191 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3192 if (textureflags & TEXF_ALPHA)
3194 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3196 if (basepixels[j] < 255)
3198 skinframe->hasalpha = true;
3202 if (r_loadfog && skinframe->hasalpha)
3204 // has transparent pixels
3205 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3206 for (j = 0;j < image_width * image_height * 4;j += 4)
3211 pixels[j+3] = basepixels[j+3];
3213 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3217 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3218 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3219 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3220 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3221 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3222 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3227 mymiplevel = savemiplevel;
3228 if (r_loadnormalmap)
3229 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3230 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3232 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3233 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3234 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3235 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3238 // _norm is the name used by tenebrae and has been adopted as standard
3239 if (r_loadnormalmap && skinframe->nmap == NULL)
3241 mymiplevel = savemiplevel;
3242 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3244 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3248 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3250 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3251 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3252 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3254 Mem_Free(bumppixels);
3256 else if (r_shadow_bumpscale_basetexture.value > 0)
3258 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3259 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3260 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3263 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3264 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3267 // _luma is supported only for tenebrae compatibility
3268 // _glow is the preferred name
3269 mymiplevel = savemiplevel;
3270 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
3272 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3273 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3274 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3275 Mem_Free(pixels);pixels = NULL;
3278 mymiplevel = savemiplevel;
3279 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3281 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3282 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3283 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3288 mymiplevel = savemiplevel;
3289 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3291 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3292 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3293 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3298 mymiplevel = savemiplevel;
3299 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3301 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3302 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3303 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3308 mymiplevel = savemiplevel;
3309 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3311 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3312 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3313 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3319 Mem_Free(basepixels);
3324 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3325 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3328 unsigned char *temp1, *temp2;
3329 skinframe_t *skinframe;
3331 if (cls.state == ca_dedicated)
3334 // if already loaded just return it, otherwise make a new skinframe
3335 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3336 if (skinframe && skinframe->base)
3339 skinframe->stain = NULL;
3340 skinframe->merged = NULL;
3341 skinframe->base = NULL;
3342 skinframe->pants = NULL;
3343 skinframe->shirt = NULL;
3344 skinframe->nmap = NULL;
3345 skinframe->gloss = NULL;
3346 skinframe->glow = NULL;
3347 skinframe->fog = NULL;
3348 skinframe->reflect = NULL;
3349 skinframe->hasalpha = false;
3351 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3355 if (developer_loading.integer)
3356 Con_Printf("loading 32bit skin \"%s\"\n", name);
3358 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3360 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3361 temp2 = temp1 + width * height * 4;
3362 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3363 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3366 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3367 if (textureflags & TEXF_ALPHA)
3369 for (i = 3;i < width * height * 4;i += 4)
3371 if (skindata[i] < 255)
3373 skinframe->hasalpha = true;
3377 if (r_loadfog && skinframe->hasalpha)
3379 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3380 memcpy(fogpixels, skindata, width * height * 4);
3381 for (i = 0;i < width * height * 4;i += 4)
3382 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3383 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3384 Mem_Free(fogpixels);
3388 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3389 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3394 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3398 skinframe_t *skinframe;
3400 if (cls.state == ca_dedicated)
3403 // if already loaded just return it, otherwise make a new skinframe
3404 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3405 if (skinframe && skinframe->base)
3408 skinframe->stain = NULL;
3409 skinframe->merged = NULL;
3410 skinframe->base = NULL;
3411 skinframe->pants = NULL;
3412 skinframe->shirt = NULL;
3413 skinframe->nmap = NULL;
3414 skinframe->gloss = NULL;
3415 skinframe->glow = NULL;
3416 skinframe->fog = NULL;
3417 skinframe->reflect = NULL;
3418 skinframe->hasalpha = false;
3420 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3424 if (developer_loading.integer)
3425 Con_Printf("loading quake skin \"%s\"\n", name);
3427 // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3428 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3429 memcpy(skinframe->qpixels, skindata, width*height);
3430 skinframe->qwidth = width;
3431 skinframe->qheight = height;
3434 for (i = 0;i < width * height;i++)
3435 featuresmask |= palette_featureflags[skindata[i]];
3437 skinframe->hasalpha = false;
3438 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3439 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3440 skinframe->qgeneratemerged = true;
3441 skinframe->qgeneratebase = skinframe->qhascolormapping;
3442 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3444 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3445 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3450 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3454 unsigned char *skindata;
3456 if (!skinframe->qpixels)
3459 if (!skinframe->qhascolormapping)
3460 colormapped = false;
3464 if (!skinframe->qgeneratebase)
3469 if (!skinframe->qgeneratemerged)
3473 width = skinframe->qwidth;
3474 height = skinframe->qheight;
3475 skindata = skinframe->qpixels;
3477 if (skinframe->qgeneratenmap)
3479 unsigned char *temp1, *temp2;
3480 skinframe->qgeneratenmap = false;
3481 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3482 temp2 = temp1 + width * height * 4;
3483 // use either a custom palette or the quake palette
3484 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3485 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3486 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3490 if (skinframe->qgenerateglow)
3492 skinframe->qgenerateglow = false;
3493 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3498 skinframe->qgeneratebase = false;
3499 skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3500 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3501 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3505 skinframe->qgeneratemerged = false;
3506 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3509 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3511 Mem_Free(skinframe->qpixels);
3512 skinframe->qpixels = NULL;
3516 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3519 skinframe_t *skinframe;
3521 if (cls.state == ca_dedicated)
3524 // if already loaded just return it, otherwise make a new skinframe
3525 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3526 if (skinframe && skinframe->base)
3529 skinframe->stain = NULL;
3530 skinframe->merged = NULL;
3531 skinframe->base = NULL;
3532 skinframe->pants = NULL;
3533 skinframe->shirt = NULL;
3534 skinframe->nmap = NULL;
3535 skinframe->gloss = NULL;
3536 skinframe->glow = NULL;
3537 skinframe->fog = NULL;
3538 skinframe->reflect = NULL;
3539 skinframe->hasalpha = false;
3541 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3545 if (developer_loading.integer)
3546 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3548 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3549 if (textureflags & TEXF_ALPHA)
3551 for (i = 0;i < width * height;i++)
3553 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3555 skinframe->hasalpha = true;
3559 if (r_loadfog && skinframe->hasalpha)
3560 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3563 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3564 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3569 skinframe_t *R_SkinFrame_LoadMissing(void)
3571 skinframe_t *skinframe;
3573 if (cls.state == ca_dedicated)
3576 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3577 skinframe->stain = NULL;
3578 skinframe->merged = NULL;
3579 skinframe->base = NULL;
3580 skinframe->pants = NULL;
3581 skinframe->shirt = NULL;
3582 skinframe->nmap = NULL;
3583 skinframe->gloss = NULL;
3584 skinframe->glow = NULL;
3585 skinframe->fog = NULL;
3586 skinframe->reflect = NULL;
3587 skinframe->hasalpha = false;
3589 skinframe->avgcolor[0] = rand() / RAND_MAX;
3590 skinframe->avgcolor[1] = rand() / RAND_MAX;
3591 skinframe->avgcolor[2] = rand() / RAND_MAX;
3592 skinframe->avgcolor[3] = 1;
3597 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3598 typedef struct suffixinfo_s
3601 qboolean flipx, flipy, flipdiagonal;
3604 static suffixinfo_t suffix[3][6] =
3607 {"px", false, false, false},
3608 {"nx", false, false, false},
3609 {"py", false, false, false},
3610 {"ny", false, false, false},
3611 {"pz", false, false, false},
3612 {"nz", false, false, false}
3615 {"posx", false, false, false},
3616 {"negx", false, false, false},
3617 {"posy", false, false, false},
3618 {"negy", false, false, false},
3619 {"posz", false, false, false},
3620 {"negz", false, false, false}
3623 {"rt", true, false, true},
3624 {"lf", false, true, true},
3625 {"ft", true, true, false},
3626 {"bk", false, false, false},
3627 {"up", true, false, true},
3628 {"dn", true, false, true}
3632 static int componentorder[4] = {0, 1, 2, 3};
3634 rtexture_t *R_LoadCubemap(const char *basename)
3636 int i, j, cubemapsize;
3637 unsigned char *cubemappixels, *image_buffer;
3638 rtexture_t *cubemaptexture;
3640 // must start 0 so the first loadimagepixels has no requested width/height
3642 cubemappixels = NULL;
3643 cubemaptexture = NULL;
3644 // keep trying different suffix groups (posx, px, rt) until one loads
3645 for (j = 0;j < 3 && !cubemappixels;j++)
3647 // load the 6 images in the suffix group
3648 for (i = 0;i < 6;i++)
3650 // generate an image name based on the base and and suffix
3651 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3653 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3655 // an image loaded, make sure width and height are equal
3656 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3658 // if this is the first image to load successfully, allocate the cubemap memory
3659 if (!cubemappixels && image_width >= 1)
3661 cubemapsize = image_width;
3662 // note this clears to black, so unavailable sides are black
3663 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3665 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3667 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3670 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3672 Mem_Free(image_buffer);
3676 // if a cubemap loaded, upload it
3679 if (developer_loading.integer)
3680 Con_Printf("loading cubemap \"%s\"\n", basename);
3682 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3683 Mem_Free(cubemappixels);
3687 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3688 if (developer_loading.integer)
3690 Con_Printf("(tried tried images ");
3691 for (j = 0;j < 3;j++)
3692 for (i = 0;i < 6;i++)
3693 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3694 Con_Print(" and was unable to find any of them).\n");
3697 return cubemaptexture;
3700 rtexture_t *R_GetCubemap(const char *basename)
3703 for (i = 0;i < r_texture_numcubemaps;i++)
3704 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3705 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3706 if (i >= MAX_CUBEMAPS)
3707 return r_texture_whitecube;
3708 r_texture_numcubemaps++;
3709 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3710 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3711 return r_texture_cubemaps[i].texture;
3714 void R_FreeCubemaps(void)
3717 for (i = 0;i < r_texture_numcubemaps;i++)
3719 if (developer_loading.integer)
3720 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3721 if (r_texture_cubemaps[i].texture)
3722 R_FreeTexture(r_texture_cubemaps[i].texture);
3724 r_texture_numcubemaps = 0;
3727 void R_Main_FreeViewCache(void)
3729 if (r_refdef.viewcache.entityvisible)
3730 Mem_Free(r_refdef.viewcache.entityvisible);
3731 if (r_refdef.viewcache.world_pvsbits)
3732 Mem_Free(r_refdef.viewcache.world_pvsbits);
3733 if (r_refdef.viewcache.world_leafvisible)
3734 Mem_Free(r_refdef.viewcache.world_leafvisible);
3735 if (r_refdef.viewcache.world_surfacevisible)
3736 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3737 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3740 void R_Main_ResizeViewCache(void)
3742 int numentities = r_refdef.scene.numentities;
3743 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3744 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3745 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3746 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3747 if (r_refdef.viewcache.maxentities < numentities)
3749 r_refdef.viewcache.maxentities = numentities;
3750 if (r_refdef.viewcache.entityvisible)
3751 Mem_Free(r_refdef.viewcache.entityvisible);
3752 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3754 if (r_refdef.viewcache.world_numclusters != numclusters)
3756 r_refdef.viewcache.world_numclusters = numclusters;
3757 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3758 if (r_refdef.viewcache.world_pvsbits)
3759 Mem_Free(r_refdef.viewcache.world_pvsbits);
3760 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3762 if (r_refdef.viewcache.world_numleafs != numleafs)
3764 r_refdef.viewcache.world_numleafs = numleafs;
3765 if (r_refdef.viewcache.world_leafvisible)
3766 Mem_Free(r_refdef.viewcache.world_leafvisible);
3767 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3769 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3771 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3772 if (r_refdef.viewcache.world_surfacevisible)
3773 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3774 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3778 extern rtexture_t *loadingscreentexture;
3779 void gl_main_start(void)
3781 loadingscreentexture = NULL;
3782 r_texture_blanknormalmap = NULL;
3783 r_texture_white = NULL;
3784 r_texture_grey128 = NULL;
3785 r_texture_black = NULL;
3786 r_texture_whitecube = NULL;
3787 r_texture_normalizationcube = NULL;
3788 r_texture_fogattenuation = NULL;
3789 r_texture_fogheighttexture = NULL;
3790 r_texture_gammaramps = NULL;
3791 r_texture_numcubemaps = 0;
3793 r_loaddds = r_texture_dds_load.integer != 0;
3794 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3796 switch(vid.renderpath)
3798 case RENDERPATH_GL20:
3799 case RENDERPATH_D3D9:
3800 case RENDERPATH_D3D10:
3801 case RENDERPATH_D3D11:
3802 case RENDERPATH_SOFT:
3803 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3804 Cvar_SetValueQuick(&gl_combine, 1);
3805 Cvar_SetValueQuick(&r_glsl, 1);
3806 r_loadnormalmap = true;
3810 case RENDERPATH_GL13:
3811 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3812 Cvar_SetValueQuick(&gl_combine, 1);
3813 Cvar_SetValueQuick(&r_glsl, 0);
3814 r_loadnormalmap = false;
3815 r_loadgloss = false;
3818 case RENDERPATH_GL11:
3819 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3820 Cvar_SetValueQuick(&gl_combine, 0);
3821 Cvar_SetValueQuick(&r_glsl, 0);
3822 r_loadnormalmap = false;
3823 r_loadgloss = false;
3826 case RENDERPATH_GLES2:
3827 Cvar_SetValueQuick(&r_textureunits, 1);
3828 Cvar_SetValueQuick(&gl_combine, 1);
3829 Cvar_SetValueQuick(&r_glsl, 1);
3830 r_loadnormalmap = true;
3831 r_loadgloss = false;
3837 R_FrameData_Reset();
3841 memset(r_queries, 0, sizeof(r_queries));
3843 r_qwskincache = NULL;
3844 r_qwskincache_size = 0;
3846 // set up r_skinframe loading system for textures
3847 memset(&r_skinframe, 0, sizeof(r_skinframe));
3848 r_skinframe.loadsequence = 1;
3849 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3851 r_main_texturepool = R_AllocTexturePool();
3852 R_BuildBlankTextures();
3854 if (vid.support.arb_texture_cube_map)
3857 R_BuildNormalizationCube();
3859 r_texture_fogattenuation = NULL;
3860 r_texture_fogheighttexture = NULL;
3861 r_texture_gammaramps = NULL;
3862 //r_texture_fogintensity = NULL;
3863 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3864 memset(&r_waterstate, 0, sizeof(r_waterstate));
3865 r_glsl_permutation = NULL;
3866 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3867 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3868 glslshaderstring = NULL;
3870 r_hlsl_permutation = NULL;
3871 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3872 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3874 hlslshaderstring = NULL;
3875 memset(&r_svbsp, 0, sizeof (r_svbsp));
3877 r_refdef.fogmasktable_density = 0;
3880 void gl_main_shutdown(void)
3883 R_FrameData_Reset();
3885 R_Main_FreeViewCache();
3887 switch(vid.renderpath)
3889 case RENDERPATH_GL11:
3890 case RENDERPATH_GL13:
3891 case RENDERPATH_GL20:
3892 case RENDERPATH_GLES2:
3894 qglDeleteQueriesARB(r_maxqueries, r_queries);
3896 case RENDERPATH_D3D9:
3897 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3899 case RENDERPATH_D3D10:
3900 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3902 case RENDERPATH_D3D11:
3903 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3905 case RENDERPATH_SOFT:
3911 memset(r_queries, 0, sizeof(r_queries));
3913 r_qwskincache = NULL;
3914 r_qwskincache_size = 0;
3916 // clear out the r_skinframe state
3917 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3918 memset(&r_skinframe, 0, sizeof(r_skinframe));
3921 Mem_Free(r_svbsp.nodes);
3922 memset(&r_svbsp, 0, sizeof (r_svbsp));
3923 R_FreeTexturePool(&r_main_texturepool);
3924 loadingscreentexture = NULL;
3925 r_texture_blanknormalmap = NULL;
3926 r_texture_white = NULL;
3927 r_texture_grey128 = NULL;
3928 r_texture_black = NULL;
3929 r_texture_whitecube = NULL;
3930 r_texture_normalizationcube = NULL;
3931 r_texture_fogattenuation = NULL;
3932 r_texture_fogheighttexture = NULL;
3933 r_texture_gammaramps = NULL;
3934 r_texture_numcubemaps = 0;
3935 //r_texture_fogintensity = NULL;
3936 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3937 memset(&r_waterstate, 0, sizeof(r_waterstate));
3940 r_glsl_permutation = NULL;
3941 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3942 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3943 glslshaderstring = NULL;
3945 r_hlsl_permutation = NULL;
3946 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3947 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3949 hlslshaderstring = NULL;
3952 extern void CL_ParseEntityLump(char *entitystring);
3953 void gl_main_newmap(void)
3955 // FIXME: move this code to client
3956 char *entities, entname[MAX_QPATH];
3958 Mem_Free(r_qwskincache);
3959 r_qwskincache = NULL;
3960 r_qwskincache_size = 0;
3963 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3964 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3966 CL_ParseEntityLump(entities);
3970 if (cl.worldmodel->brush.entities)
3971 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3973 R_Main_FreeViewCache();
3975 R_FrameData_Reset();
3978 void GL_Main_Init(void)
3980 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3982 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3983 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3984 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3985 if (gamemode == GAME_NEHAHRA)
3987 Cvar_RegisterVariable (&gl_fogenable);
3988 Cvar_RegisterVariable (&gl_fogdensity);
3989 Cvar_RegisterVariable (&gl_fogred);
3990 Cvar_RegisterVariable (&gl_foggreen);
3991 Cvar_RegisterVariable (&gl_fogblue);
3992 Cvar_RegisterVariable (&gl_fogstart);
3993 Cvar_RegisterVariable (&gl_fogend);
3994 Cvar_RegisterVariable (&gl_skyclip);
3996 Cvar_RegisterVariable(&r_motionblur);
3997 Cvar_RegisterVariable(&r_motionblur_maxblur);
3998 Cvar_RegisterVariable(&r_motionblur_bmin);
3999 Cvar_RegisterVariable(&r_motionblur_vmin);
4000 Cvar_RegisterVariable(&r_motionblur_vmax);
4001 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4002 Cvar_RegisterVariable(&r_motionblur_randomize);
4003 Cvar_RegisterVariable(&r_damageblur);
4004 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4005 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4006 Cvar_RegisterVariable(&r_equalize_entities_by);
4007 Cvar_RegisterVariable(&r_equalize_entities_to);
4008 Cvar_RegisterVariable(&r_depthfirst);
4009 Cvar_RegisterVariable(&r_useinfinitefarclip);
4010 Cvar_RegisterVariable(&r_farclip_base);
4011 Cvar_RegisterVariable(&r_farclip_world);
4012 Cvar_RegisterVariable(&r_nearclip);
4013 Cvar_RegisterVariable(&r_showbboxes);
4014 Cvar_RegisterVariable(&r_showsurfaces);
4015 Cvar_RegisterVariable(&r_showtris);
4016 Cvar_RegisterVariable(&r_shownormals);
4017 Cvar_RegisterVariable(&r_showlighting);
4018 Cvar_RegisterVariable(&r_showshadowvolumes);
4019 Cvar_RegisterVariable(&r_showcollisionbrushes);
4020 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4021 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4022 Cvar_RegisterVariable(&r_showdisabledepthtest);
4023 Cvar_RegisterVariable(&r_drawportals);
4024 Cvar_RegisterVariable(&r_drawentities);
4025 Cvar_RegisterVariable(&r_draw2d);
4026 Cvar_RegisterVariable(&r_drawworld);
4027 Cvar_RegisterVariable(&r_cullentities_trace);
4028 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4029 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4030 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4031 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4032 Cvar_RegisterVariable(&r_drawviewmodel);
4033 Cvar_RegisterVariable(&r_drawexteriormodel);
4034 Cvar_RegisterVariable(&r_speeds);
4035 Cvar_RegisterVariable(&r_fullbrights);
4036 Cvar_RegisterVariable(&r_wateralpha);
4037 Cvar_RegisterVariable(&r_dynamic);
4038 Cvar_RegisterVariable(&r_fakelight);
4039 Cvar_RegisterVariable(&r_fakelight_intensity);
4040 Cvar_RegisterVariable(&r_fullbright);
4041 Cvar_RegisterVariable(&r_shadows);
4042 Cvar_RegisterVariable(&r_shadows_darken);
4043 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4044 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4045 Cvar_RegisterVariable(&r_shadows_throwdistance);
4046 Cvar_RegisterVariable(&r_shadows_throwdirection);
4047 Cvar_RegisterVariable(&r_shadows_focus);
4048 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4049 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4050 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4051 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4052 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4053 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4054 Cvar_RegisterVariable(&r_fog_exp2);
4055 Cvar_RegisterVariable(&r_drawfog);
4056 Cvar_RegisterVariable(&r_transparentdepthmasking);
4057 Cvar_RegisterVariable(&r_texture_dds_load);
4058 Cvar_RegisterVariable(&r_texture_dds_save);
4059 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4060 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4061 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4062 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4063 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4064 Cvar_RegisterVariable(&r_textureunits);
4065 Cvar_RegisterVariable(&gl_combine);
4066 Cvar_RegisterVariable(&r_glsl);
4067 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4068 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4069 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4070 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4071 Cvar_RegisterVariable(&r_glsl_postprocess);
4072 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4073 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4074 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4075 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4076 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4077 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4078 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4079 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4081 Cvar_RegisterVariable(&r_water);
4082 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4083 Cvar_RegisterVariable(&r_water_clippingplanebias);
4084 Cvar_RegisterVariable(&r_water_refractdistort);
4085 Cvar_RegisterVariable(&r_water_reflectdistort);
4086 Cvar_RegisterVariable(&r_water_scissormode);
4087 Cvar_RegisterVariable(&r_lerpsprites);
4088 Cvar_RegisterVariable(&r_lerpmodels);
4089 Cvar_RegisterVariable(&r_lerplightstyles);
4090 Cvar_RegisterVariable(&r_waterscroll);
4091 Cvar_RegisterVariable(&r_bloom);
4092 Cvar_RegisterVariable(&r_bloom_colorscale);
4093 Cvar_RegisterVariable(&r_bloom_brighten);
4094 Cvar_RegisterVariable(&r_bloom_blur);
4095 Cvar_RegisterVariable(&r_bloom_resolution);
4096 Cvar_RegisterVariable(&r_bloom_colorexponent);
4097 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4098 Cvar_RegisterVariable(&r_hdr);
4099 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4100 Cvar_RegisterVariable(&r_hdr_glowintensity);
4101 Cvar_RegisterVariable(&r_hdr_range);
4102 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4103 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4104 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4105 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4106 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4107 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4108 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4109 Cvar_RegisterVariable(&developer_texturelogging);
4110 Cvar_RegisterVariable(&gl_lightmaps);
4111 Cvar_RegisterVariable(&r_test);
4112 Cvar_RegisterVariable(&r_glsl_saturation);
4113 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4114 Cvar_RegisterVariable(&r_framedatasize);
4115 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4116 Cvar_SetValue("r_fullbrights", 0);
4117 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4119 Cvar_RegisterVariable(&r_track_sprites);
4120 Cvar_RegisterVariable(&r_track_sprites_flags);
4121 Cvar_RegisterVariable(&r_track_sprites_scalew);
4122 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4123 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4124 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4125 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4126 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4129 extern void R_Textures_Init(void);
4130 extern void GL_Draw_Init(void);
4131 extern void GL_Main_Init(void);
4132 extern void R_Shadow_Init(void);
4133 extern void R_Sky_Init(void);
4134 extern void GL_Surf_Init(void);
4135 extern void R_Particles_Init(void);
4136 extern void R_Explosion_Init(void);
4137 extern void gl_backend_init(void);
4138 extern void Sbar_Init(void);
4139 extern void R_LightningBeams_Init(void);
4140 extern void Mod_RenderInit(void);
4141 extern void Font_Init(void);
4143 void Render_Init(void)
4156 R_LightningBeams_Init();
4165 extern char *ENGINE_EXTENSIONS;
4168 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4169 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4170 gl_version = (const char *)qglGetString(GL_VERSION);
4171 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4175 if (!gl_platformextensions)
4176 gl_platformextensions = "";
4178 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4179 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4180 Con_Printf("GL_VERSION: %s\n", gl_version);
4181 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4182 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4184 VID_CheckExtensions();
4186 // LordHavoc: report supported extensions
4187 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4189 // clear to black (loading plaque will be seen over this)
4190 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4193 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4197 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4199 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4202 p = r_refdef.view.frustum + i;
4207 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4211 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4215 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4219 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4223 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4227 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4231 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4235 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4243 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4247 for (i = 0;i < numplanes;i++)
4254 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4258 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4262 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4266 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4270 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4274 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4278 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4282 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4290 //==================================================================================
4292 // LordHavoc: this stores temporary data used within the same frame
4294 typedef struct r_framedata_mem_s
4296 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4297 size_t size; // how much usable space
4298 size_t current; // how much space in use
4299 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4300 size_t wantedsize; // how much space was allocated
4301 unsigned char *data; // start of real data (16byte aligned)
4305 static r_framedata_mem_t *r_framedata_mem;
4307 void R_FrameData_Reset(void)
4309 while (r_framedata_mem)
4311 r_framedata_mem_t *next = r_framedata_mem->purge;
4312 Mem_Free(r_framedata_mem);
4313 r_framedata_mem = next;
4317 void R_FrameData_Resize(void)
4320 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4321 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4322 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4324 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4325 newmem->wantedsize = wantedsize;
4326 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4327 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4328 newmem->current = 0;
4330 newmem->purge = r_framedata_mem;
4331 r_framedata_mem = newmem;
4335 void R_FrameData_NewFrame(void)
4337 R_FrameData_Resize();
4338 if (!r_framedata_mem)
4340 // if we ran out of space on the last frame, free the old memory now
4341 while (r_framedata_mem->purge)
4343 // repeatedly remove the second item in the list, leaving only head
4344 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4345 Mem_Free(r_framedata_mem->purge);
4346 r_framedata_mem->purge = next;
4348 // reset the current mem pointer
4349 r_framedata_mem->current = 0;
4350 r_framedata_mem->mark = 0;
4353 void *R_FrameData_Alloc(size_t size)
4357 // align to 16 byte boundary - the data pointer is already aligned, so we
4358 // only need to ensure the size of every allocation is also aligned
4359 size = (size + 15) & ~15;
4361 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4363 // emergency - we ran out of space, allocate more memory
4364 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4365 R_FrameData_Resize();
4368 data = r_framedata_mem->data + r_framedata_mem->current;
4369 r_framedata_mem->current += size;
4371 // count the usage for stats
4372 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4373 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4375 return (void *)data;
4378 void *R_FrameData_Store(size_t size, void *data)
4380 void *d = R_FrameData_Alloc(size);
4382 memcpy(d, data, size);
4386 void R_FrameData_SetMark(void)
4388 if (!r_framedata_mem)
4390 r_framedata_mem->mark = r_framedata_mem->current;
4393 void R_FrameData_ReturnToMark(void)
4395 if (!r_framedata_mem)
4397 r_framedata_mem->current = r_framedata_mem->mark;
4400 //==================================================================================
4402 // LordHavoc: animcache originally written by Echon, rewritten since then
4405 * Animation cache prevents re-generating mesh data for an animated model
4406 * multiple times in one frame for lighting, shadowing, reflections, etc.
4409 void R_AnimCache_Free(void)
4413 void R_AnimCache_ClearCache(void)
4416 entity_render_t *ent;
4418 for (i = 0;i < r_refdef.scene.numentities;i++)
4420 ent = r_refdef.scene.entities[i];
4421 ent->animcache_vertex3f = NULL;
4422 ent->animcache_normal3f = NULL;
4423 ent->animcache_svector3f = NULL;
4424 ent->animcache_tvector3f = NULL;
4425 ent->animcache_vertexmesh = NULL;
4426 ent->animcache_vertex3fbuffer = NULL;
4427 ent->animcache_vertexmeshbuffer = NULL;
4431 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4435 // check if we need the meshbuffers
4436 if (!vid.useinterleavedarrays)
4439 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4440 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4441 // TODO: upload vertex3f buffer?
4442 if (ent->animcache_vertexmesh)
4444 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4445 for (i = 0;i < numvertices;i++)
4446 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4447 if (ent->animcache_svector3f)
4448 for (i = 0;i < numvertices;i++)
4449 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4450 if (ent->animcache_tvector3f)
4451 for (i = 0;i < numvertices;i++)
4452 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4453 if (ent->animcache_normal3f)
4454 for (i = 0;i < numvertices;i++)
4455 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4456 // TODO: upload vertexmeshbuffer?
4460 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4462 dp_model_t *model = ent->model;
4464 // see if it's already cached this frame
4465 if (ent->animcache_vertex3f)
4467 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4468 if (wantnormals || wanttangents)
4470 if (ent->animcache_normal3f)
4471 wantnormals = false;
4472 if (ent->animcache_svector3f)
4473 wanttangents = false;
4474 if (wantnormals || wanttangents)
4476 numvertices = model->surfmesh.num_vertices;
4478 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4481 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4482 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4484 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4485 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4491 // see if this ent is worth caching
4492 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4494 // get some memory for this entity and generate mesh data
4495 numvertices = model->surfmesh.num_vertices;
4496 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4498 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4501 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4502 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4504 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4505 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4510 void R_AnimCache_CacheVisibleEntities(void)
4513 qboolean wantnormals = true;
4514 qboolean wanttangents = !r_showsurfaces.integer;
4516 switch(vid.renderpath)
4518 case RENDERPATH_GL20:
4519 case RENDERPATH_D3D9:
4520 case RENDERPATH_D3D10:
4521 case RENDERPATH_D3D11:
4522 case RENDERPATH_GLES2:
4524 case RENDERPATH_GL13:
4525 case RENDERPATH_GL11:
4526 wanttangents = false;
4528 case RENDERPATH_SOFT:
4532 if (r_shownormals.integer)
4533 wanttangents = wantnormals = true;
4535 // TODO: thread this
4536 // NOTE: R_PrepareRTLights() also caches entities
4538 for (i = 0;i < r_refdef.scene.numentities;i++)
4539 if (r_refdef.viewcache.entityvisible[i])
4540 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4543 //==================================================================================
4545 static void R_View_UpdateEntityLighting (void)
4548 entity_render_t *ent;
4549 vec3_t tempdiffusenormal, avg;
4550 vec_t f, fa, fd, fdd;
4551 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4553 for (i = 0;i < r_refdef.scene.numentities;i++)
4555 ent = r_refdef.scene.entities[i];
4557 // skip unseen models
4558 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4562 if (ent->model && ent->model->brush.num_leafs)
4564 // TODO: use modellight for r_ambient settings on world?
4565 VectorSet(ent->modellight_ambient, 0, 0, 0);
4566 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4567 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4571 // fetch the lighting from the worldmodel data
4572 VectorClear(ent->modellight_ambient);
4573 VectorClear(ent->modellight_diffuse);
4574 VectorClear(tempdiffusenormal);
4575 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4578 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4580 // complete lightning for lit sprites
4581 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4582 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4584 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4585 org[2] = org[2] + r_overheadsprites_pushback.value;
4586 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4589 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4591 if(ent->flags & RENDER_EQUALIZE)
4593 // first fix up ambient lighting...
4594 if(r_equalize_entities_minambient.value > 0)
4596 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4599 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4600 if(fa < r_equalize_entities_minambient.value * fd)
4603 // fa'/fd' = minambient
4604 // fa'+0.25*fd' = fa+0.25*fd
4606 // fa' = fd' * minambient
4607 // fd'*(0.25+minambient) = fa+0.25*fd
4609 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4610 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4612 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4613 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
4614 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4615 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4620 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4622 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4623 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4627 // adjust brightness and saturation to target
4628 avg[0] = avg[1] = avg[2] = fa / f;
4629 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4630 avg[0] = avg[1] = avg[2] = fd / f;
4631 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4637 VectorSet(ent->modellight_ambient, 1, 1, 1);
4639 // move the light direction into modelspace coordinates for lighting code
4640 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4641 if(VectorLength2(ent->modellight_lightdir) == 0)
4642 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4643 VectorNormalize(ent->modellight_lightdir);
4647 #define MAX_LINEOFSIGHTTRACES 64
4649 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4652 vec3_t boxmins, boxmaxs;
4655 dp_model_t *model = r_refdef.scene.worldmodel;
4657 if (!model || !model->brush.TraceLineOfSight)
4660 // expand the box a little
4661 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4662 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4663 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4664 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4665 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4666 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4668 // return true if eye is inside enlarged box
4669 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4673 VectorCopy(eye, start);
4674 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4675 if (model->brush.TraceLineOfSight(model, start, end))
4678 // try various random positions
4679 for (i = 0;i < numsamples;i++)
4681 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4682 if (model->brush.TraceLineOfSight(model, start, end))
4690 static void R_View_UpdateEntityVisible (void)
4695 entity_render_t *ent;
4697 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4698 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4699 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4700 : RENDER_EXTERIORMODEL;
4701 if (!r_drawviewmodel.integer)
4702 renderimask |= RENDER_VIEWMODEL;
4703 if (!r_drawexteriormodel.integer)
4704 renderimask |= RENDER_EXTERIORMODEL;
4705 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4707 // worldmodel can check visibility
4708 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4709 for (i = 0;i < r_refdef.scene.numentities;i++)
4711 ent = r_refdef.scene.entities[i];
4712 if (!(ent->flags & renderimask))
4713 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
4714 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4715 r_refdef.viewcache.entityvisible[i] = true;
4717 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4718 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4720 for (i = 0;i < r_refdef.scene.numentities;i++)
4722 ent = r_refdef.scene.entities[i];
4723 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4725 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4727 continue; // temp entities do pvs only
4728 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4729 ent->last_trace_visibility = realtime;
4730 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4731 r_refdef.viewcache.entityvisible[i] = 0;
4738 // no worldmodel or it can't check visibility
4739 for (i = 0;i < r_refdef.scene.numentities;i++)
4741 ent = r_refdef.scene.entities[i];
4742 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
4747 /// only used if skyrendermasked, and normally returns false
4748 int R_DrawBrushModelsSky (void)
4751 entity_render_t *ent;
4754 for (i = 0;i < r_refdef.scene.numentities;i++)
4756 if (!r_refdef.viewcache.entityvisible[i])
4758 ent = r_refdef.scene.entities[i];
4759 if (!ent->model || !ent->model->DrawSky)
4761 ent->model->DrawSky(ent);
4767 static void R_DrawNoModel(entity_render_t *ent);
4768 static void R_DrawModels(void)
4771 entity_render_t *ent;
4773 for (i = 0;i < r_refdef.scene.numentities;i++)
4775 if (!r_refdef.viewcache.entityvisible[i])
4777 ent = r_refdef.scene.entities[i];
4778 r_refdef.stats.entities++;
4779 if (ent->model && ent->model->Draw != NULL)
4780 ent->model->Draw(ent);
4786 static void R_DrawModelsDepth(void)
4789 entity_render_t *ent;
4791 for (i = 0;i < r_refdef.scene.numentities;i++)
4793 if (!r_refdef.viewcache.entityvisible[i])
4795 ent = r_refdef.scene.entities[i];
4796 if (ent->model && ent->model->DrawDepth != NULL)
4797 ent->model->DrawDepth(ent);
4801 static void R_DrawModelsDebug(void)
4804 entity_render_t *ent;
4806 for (i = 0;i < r_refdef.scene.numentities;i++)
4808 if (!r_refdef.viewcache.entityvisible[i])
4810 ent = r_refdef.scene.entities[i];
4811 if (ent->model && ent->model->DrawDebug != NULL)
4812 ent->model->DrawDebug(ent);
4816 static void R_DrawModelsAddWaterPlanes(void)
4819 entity_render_t *ent;
4821 for (i = 0;i < r_refdef.scene.numentities;i++)
4823 if (!r_refdef.viewcache.entityvisible[i])
4825 ent = r_refdef.scene.entities[i];
4826 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4827 ent->model->DrawAddWaterPlanes(ent);
4831 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4833 if (r_hdr_irisadaptation.integer)
4837 vec3_t diffusenormal;
4842 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4843 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4844 brightness = max(0.0000001f, brightness);
4845 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4846 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4847 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4848 current = r_hdr_irisadaptation_value.value;
4850 current = min(current + adjust, goal);
4851 else if (current > goal)
4852 current = max(current - adjust, goal);
4853 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4854 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4856 else if (r_hdr_irisadaptation_value.value != 1.0f)
4857 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4860 static void R_View_SetFrustum(const int *scissor)
4863 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4864 vec3_t forward, left, up, origin, v;
4868 // flipped x coordinates (because x points left here)
4869 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4870 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4872 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4873 switch(vid.renderpath)
4875 case RENDERPATH_D3D9:
4876 case RENDERPATH_D3D10:
4877 case RENDERPATH_D3D11:
4878 case RENDERPATH_SOFT:
4879 // non-flipped y coordinates
4880 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4881 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4883 case RENDERPATH_GL11:
4884 case RENDERPATH_GL13:
4885 case RENDERPATH_GL20:
4886 case RENDERPATH_GLES2:
4887 // non-flipped y coordinates
4888 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4889 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4894 // we can't trust r_refdef.view.forward and friends in reflected scenes
4895 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4898 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4899 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4900 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4901 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4902 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4903 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4904 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4905 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4906 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4907 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4908 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4909 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4913 zNear = r_refdef.nearclip;
4914 nudge = 1.0 - 1.0 / (1<<23);
4915 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4916 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4917 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4918 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4919 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4920 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4921 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4922 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4928 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4929 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4930 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4931 r_refdef.view.frustum[0].dist = m[15] - m[12];
4933 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4934 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4935 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4936 r_refdef.view.frustum[1].dist = m[15] + m[12];
4938 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4939 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4940 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4941 r_refdef.view.frustum[2].dist = m[15] - m[13];
4943 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4944 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4945 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4946 r_refdef.view.frustum[3].dist = m[15] + m[13];
4948 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4949 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4950 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4951 r_refdef.view.frustum[4].dist = m[15] - m[14];
4953 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4954 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4955 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4956 r_refdef.view.frustum[5].dist = m[15] + m[14];
4959 if (r_refdef.view.useperspective)
4961 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4962 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
4963 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
4964 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
4965 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
4967 // then the normals from the corners relative to origin
4968 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4969 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4970 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4971 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4973 // in a NORMAL view, forward cross left == up
4974 // in a REFLECTED view, forward cross left == down
4975 // so our cross products above need to be adjusted for a left handed coordinate system
4976 CrossProduct(forward, left, v);
4977 if(DotProduct(v, up) < 0)
4979 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4980 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
4981 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
4982 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
4985 // Leaving those out was a mistake, those were in the old code, and they
4986 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4987 // I couldn't reproduce it after adding those normalizations. --blub
4988 VectorNormalize(r_refdef.view.frustum[0].normal);
4989 VectorNormalize(r_refdef.view.frustum[1].normal);
4990 VectorNormalize(r_refdef.view.frustum[2].normal);
4991 VectorNormalize(r_refdef.view.frustum[3].normal);
4993 // make the corners absolute
4994 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
4995 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
4996 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
4997 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5000 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5002 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5003 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5004 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5005 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5006 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5010 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5011 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5012 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5013 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5014 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5015 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5016 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5017 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5018 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5019 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5021 r_refdef.view.numfrustumplanes = 5;
5023 if (r_refdef.view.useclipplane)
5025 r_refdef.view.numfrustumplanes = 6;
5026 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5029 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5030 PlaneClassify(r_refdef.view.frustum + i);
5032 // LordHavoc: note to all quake engine coders, Quake had a special case
5033 // for 90 degrees which assumed a square view (wrong), so I removed it,
5034 // Quake2 has it disabled as well.
5036 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5037 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5038 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5039 //PlaneClassify(&frustum[0]);
5041 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5042 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5043 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5044 //PlaneClassify(&frustum[1]);
5046 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5047 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5048 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5049 //PlaneClassify(&frustum[2]);
5051 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5052 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5053 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5054 //PlaneClassify(&frustum[3]);
5057 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5058 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5059 //PlaneClassify(&frustum[4]);
5062 void R_View_UpdateWithScissor(const int *myscissor)
5064 R_Main_ResizeViewCache();
5065 R_View_SetFrustum(myscissor);
5066 R_View_WorldVisibility(r_refdef.view.useclipplane);
5067 R_View_UpdateEntityVisible();
5068 R_View_UpdateEntityLighting();
5071 void R_View_Update(void)
5073 R_Main_ResizeViewCache();
5074 R_View_SetFrustum(NULL);
5075 R_View_WorldVisibility(r_refdef.view.useclipplane);
5076 R_View_UpdateEntityVisible();
5077 R_View_UpdateEntityLighting();
5080 void R_SetupView(qboolean allowwaterclippingplane)
5082 const float *customclipplane = NULL;
5084 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5086 // LordHavoc: couldn't figure out how to make this approach the
5087 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5088 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5089 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5090 dist = r_refdef.view.clipplane.dist;
5091 plane[0] = r_refdef.view.clipplane.normal[0];
5092 plane[1] = r_refdef.view.clipplane.normal[1];
5093 plane[2] = r_refdef.view.clipplane.normal[2];
5095 customclipplane = plane;
5098 if (!r_refdef.view.useperspective)
5099 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5100 else if (vid.stencil && r_useinfinitefarclip.integer)
5101 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5103 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5104 R_SetViewport(&r_refdef.view.viewport);
5107 void R_EntityMatrix(const matrix4x4_t *matrix)
5109 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5111 gl_modelmatrixchanged = false;
5112 gl_modelmatrix = *matrix;
5113 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5114 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5115 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5116 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5118 switch(vid.renderpath)
5120 case RENDERPATH_D3D9:
5122 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5123 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5126 case RENDERPATH_D3D10:
5127 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5129 case RENDERPATH_D3D11:
5130 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5132 case RENDERPATH_GL13:
5133 case RENDERPATH_GL11:
5134 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5136 case RENDERPATH_SOFT:
5137 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5138 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5140 case RENDERPATH_GL20:
5141 case RENDERPATH_GLES2:
5142 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5143 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5149 void R_ResetViewRendering2D(void)
5151 r_viewport_t viewport;
5154 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5155 R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
5156 R_SetViewport(&viewport);
5157 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5158 GL_Color(1, 1, 1, 1);
5159 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5160 GL_BlendFunc(GL_ONE, GL_ZERO);
5161 GL_ScissorTest(false);
5162 GL_DepthMask(false);
5163 GL_DepthRange(0, 1);
5164 GL_DepthTest(false);
5165 GL_DepthFunc(GL_LEQUAL);
5166 R_EntityMatrix(&identitymatrix);
5167 R_Mesh_ResetTextureState();
5168 GL_PolygonOffset(0, 0);
5169 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5170 switch(vid.renderpath)
5172 case RENDERPATH_GL11:
5173 case RENDERPATH_GL13:
5174 case RENDERPATH_GL20:
5175 case RENDERPATH_GLES2:
5176 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5178 case RENDERPATH_D3D9:
5179 case RENDERPATH_D3D10:
5180 case RENDERPATH_D3D11:
5181 case RENDERPATH_SOFT:
5184 GL_CullFace(GL_NONE);
5187 void R_ResetViewRendering3D(void)
5192 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5193 GL_Color(1, 1, 1, 1);
5194 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5195 GL_BlendFunc(GL_ONE, GL_ZERO);
5196 GL_ScissorTest(true);
5198 GL_DepthRange(0, 1);
5200 GL_DepthFunc(GL_LEQUAL);
5201 R_EntityMatrix(&identitymatrix);
5202 R_Mesh_ResetTextureState();
5203 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5204 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5205 switch(vid.renderpath)
5207 case RENDERPATH_GL11:
5208 case RENDERPATH_GL13:
5209 case RENDERPATH_GL20:
5210 case RENDERPATH_GLES2:
5211 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5213 case RENDERPATH_D3D9:
5214 case RENDERPATH_D3D10:
5215 case RENDERPATH_D3D11:
5216 case RENDERPATH_SOFT:
5219 GL_CullFace(r_refdef.view.cullface_back);
5224 R_RenderView_UpdateViewVectors
5227 static void R_RenderView_UpdateViewVectors(void)
5229 // break apart the view matrix into vectors for various purposes
5230 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5231 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5232 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5233 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5234 // make an inverted copy of the view matrix for tracking sprites
5235 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5238 void R_RenderScene(void);
5239 void R_RenderWaterPlanes(void);
5241 static void R_Water_StartFrame(void)
5244 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5245 r_waterstate_waterplane_t *p;
5247 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5250 switch(vid.renderpath)
5252 case RENDERPATH_GL20:
5253 case RENDERPATH_D3D9:
5254 case RENDERPATH_D3D10:
5255 case RENDERPATH_D3D11:
5256 case RENDERPATH_SOFT:
5257 case RENDERPATH_GLES2:
5259 case RENDERPATH_GL13:
5260 case RENDERPATH_GL11:
5264 // set waterwidth and waterheight to the water resolution that will be
5265 // used (often less than the screen resolution for faster rendering)
5266 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5267 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5269 // calculate desired texture sizes
5270 // can't use water if the card does not support the texture size
5271 if (!r_water.integer || r_showsurfaces.integer)
5272 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5273 else if (vid.support.arb_texture_non_power_of_two)
5275 texturewidth = waterwidth;
5276 textureheight = waterheight;
5277 camerawidth = waterwidth;
5278 cameraheight = waterheight;
5282 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5283 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5284 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5285 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5288 // allocate textures as needed
5289 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5291 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5292 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5294 if (p->texture_refraction)
5295 R_FreeTexture(p->texture_refraction);
5296 p->texture_refraction = NULL;
5297 if (p->texture_reflection)
5298 R_FreeTexture(p->texture_reflection);
5299 p->texture_reflection = NULL;
5300 if (p->texture_camera)
5301 R_FreeTexture(p->texture_camera);
5302 p->texture_camera = NULL;
5304 memset(&r_waterstate, 0, sizeof(r_waterstate));
5305 r_waterstate.texturewidth = texturewidth;
5306 r_waterstate.textureheight = textureheight;
5307 r_waterstate.camerawidth = camerawidth;
5308 r_waterstate.cameraheight = cameraheight;
5311 if (r_waterstate.texturewidth)
5313 r_waterstate.enabled = true;
5315 // when doing a reduced render (HDR) we want to use a smaller area
5316 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5317 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5319 // set up variables that will be used in shader setup
5320 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5321 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5322 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5323 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5326 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5327 r_waterstate.numwaterplanes = 0;
5330 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5332 int triangleindex, planeindex;
5338 r_waterstate_waterplane_t *p;
5339 texture_t *t = R_GetCurrentTexture(surface->texture);
5341 // just use the first triangle with a valid normal for any decisions
5342 VectorClear(normal);
5343 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5345 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5346 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5347 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5348 TriangleNormal(vert[0], vert[1], vert[2], normal);
5349 if (VectorLength2(normal) >= 0.001)
5353 VectorCopy(normal, plane.normal);
5354 VectorNormalize(plane.normal);
5355 plane.dist = DotProduct(vert[0], plane.normal);
5356 PlaneClassify(&plane);
5357 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5359 // skip backfaces (except if nocullface is set)
5360 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5362 VectorNegate(plane.normal, plane.normal);
5364 PlaneClassify(&plane);
5368 // find a matching plane if there is one
5369 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5370 if(p->camera_entity == t->camera_entity)
5371 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5373 if (planeindex >= r_waterstate.maxwaterplanes)
5374 return; // nothing we can do, out of planes
5376 // if this triangle does not fit any known plane rendered this frame, add one
5377 if (planeindex >= r_waterstate.numwaterplanes)
5379 // store the new plane
5380 r_waterstate.numwaterplanes++;
5382 // clear materialflags and pvs
5383 p->materialflags = 0;
5384 p->pvsvalid = false;
5385 p->camera_entity = t->camera_entity;
5386 VectorCopy(surface->mins, p->mins);
5387 VectorCopy(surface->maxs, p->maxs);
5392 p->mins[0] = min(p->mins[0], surface->mins[0]);
5393 p->mins[1] = min(p->mins[1], surface->mins[1]);
5394 p->mins[2] = min(p->mins[2], surface->mins[2]);
5395 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5396 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5397 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5399 // merge this surface's materialflags into the waterplane
5400 p->materialflags |= t->currentmaterialflags;
5401 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5403 // merge this surface's PVS into the waterplane
5404 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5405 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5406 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5408 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5414 static void R_Water_ProcessPlanes(void)
5417 r_refdef_view_t originalview;
5418 r_refdef_view_t myview;
5420 r_waterstate_waterplane_t *p;
5423 originalview = r_refdef.view;
5425 // make sure enough textures are allocated
5426 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5428 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5430 if (!p->texture_refraction)
5431 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5432 if (!p->texture_refraction)
5435 else if (p->materialflags & MATERIALFLAG_CAMERA)
5437 if (!p->texture_camera)
5438 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5439 if (!p->texture_camera)
5443 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5445 if (!p->texture_reflection)
5446 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5447 if (!p->texture_reflection)
5453 r_refdef.view = originalview;
5454 r_refdef.view.showdebug = false;
5455 r_refdef.view.width = r_waterstate.waterwidth;
5456 r_refdef.view.height = r_waterstate.waterheight;
5457 r_refdef.view.useclipplane = true;
5458 myview = r_refdef.view;
5459 r_waterstate.renderingscene = true;
5460 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5462 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5464 r_refdef.view = myview;
5465 if(r_water_scissormode.integer)
5468 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5469 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5472 // render reflected scene and copy into texture
5473 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5474 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5475 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5476 r_refdef.view.clipplane = p->plane;
5478 // reverse the cullface settings for this render
5479 r_refdef.view.cullface_front = GL_FRONT;
5480 r_refdef.view.cullface_back = GL_BACK;
5481 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5483 r_refdef.view.usecustompvs = true;
5485 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5487 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5490 R_ResetViewRendering3D();
5491 R_ClearScreen(r_refdef.fogenabled);
5492 if(r_water_scissormode.integer & 2)
5493 R_View_UpdateWithScissor(myscissor);
5496 if(r_water_scissormode.integer & 1)
5497 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5500 R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5503 // render the normal view scene and copy into texture
5504 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
5505 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5507 r_refdef.view = myview;
5508 if(r_water_scissormode.integer)
5511 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5512 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5515 r_waterstate.renderingrefraction = true;
5517 r_refdef.view.clipplane = p->plane;
5518 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5519 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5521 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5523 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5524 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5525 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5526 R_RenderView_UpdateViewVectors();
5527 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5529 r_refdef.view.usecustompvs = true;
5530 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5534 PlaneClassify(&r_refdef.view.clipplane);
5536 R_ResetViewRendering3D();
5537 R_ClearScreen(r_refdef.fogenabled);
5538 if(r_water_scissormode.integer & 2)
5539 R_View_UpdateWithScissor(myscissor);
5542 if(r_water_scissormode.integer & 1)
5543 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5546 R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5547 r_waterstate.renderingrefraction = false;
5549 else if (p->materialflags & MATERIALFLAG_CAMERA)
5551 r_refdef.view = myview;
5553 r_refdef.view.clipplane = p->plane;
5554 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5555 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5557 r_refdef.view.width = r_waterstate.camerawidth;
5558 r_refdef.view.height = r_waterstate.cameraheight;
5559 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5560 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5562 if(p->camera_entity)
5564 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5565 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5568 // note: all of the view is used for displaying... so
5569 // there is no use in scissoring
5571 // reverse the cullface settings for this render
5572 r_refdef.view.cullface_front = GL_FRONT;
5573 r_refdef.view.cullface_back = GL_BACK;
5574 // also reverse the view matrix
5575 Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
5576 R_RenderView_UpdateViewVectors();
5577 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5579 r_refdef.view.usecustompvs = true;
5580 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5583 // camera needs no clipplane
5584 r_refdef.view.useclipplane = false;
5586 PlaneClassify(&r_refdef.view.clipplane);
5588 R_ResetViewRendering3D();
5589 R_ClearScreen(r_refdef.fogenabled);
5593 R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5594 r_waterstate.renderingrefraction = false;
5598 r_waterstate.renderingscene = false;
5599 r_refdef.view = originalview;
5600 R_ResetViewRendering3D();
5601 R_ClearScreen(r_refdef.fogenabled);
5605 r_refdef.view = originalview;
5606 r_waterstate.renderingscene = false;
5607 Cvar_SetValueQuick(&r_water, 0);
5608 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5612 void R_Bloom_StartFrame(void)
5614 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5616 switch(vid.renderpath)
5618 case RENDERPATH_GL20:
5619 case RENDERPATH_D3D9:
5620 case RENDERPATH_D3D10:
5621 case RENDERPATH_D3D11:
5622 case RENDERPATH_SOFT:
5623 case RENDERPATH_GLES2:
5625 case RENDERPATH_GL13:
5626 case RENDERPATH_GL11:
5630 // set bloomwidth and bloomheight to the bloom resolution that will be
5631 // used (often less than the screen resolution for faster rendering)
5632 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5633 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5634 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5635 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5636 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5638 // calculate desired texture sizes
5639 if (vid.support.arb_texture_non_power_of_two)
5641 screentexturewidth = r_refdef.view.width;
5642 screentextureheight = r_refdef.view.height;
5643 bloomtexturewidth = r_bloomstate.bloomwidth;
5644 bloomtextureheight = r_bloomstate.bloomheight;
5648 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5649 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5650 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5651 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5654 if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
5656 Cvar_SetValueQuick(&r_hdr, 0);
5657 Cvar_SetValueQuick(&r_bloom, 0);
5658 Cvar_SetValueQuick(&r_motionblur, 0);
5659 Cvar_SetValueQuick(&r_damageblur, 0);
5662 if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
5663 screentexturewidth = screentextureheight = 0;
5664 if (!r_hdr.integer && !r_bloom.integer)
5665 bloomtexturewidth = bloomtextureheight = 0;
5667 // allocate textures as needed
5668 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5670 if (r_bloomstate.texture_screen)
5671 R_FreeTexture(r_bloomstate.texture_screen);
5672 r_bloomstate.texture_screen = NULL;
5673 r_bloomstate.screentexturewidth = screentexturewidth;
5674 r_bloomstate.screentextureheight = screentextureheight;
5675 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5676 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
5678 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5680 if (r_bloomstate.texture_bloom)
5681 R_FreeTexture(r_bloomstate.texture_bloom);
5682 r_bloomstate.texture_bloom = NULL;
5683 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5684 r_bloomstate.bloomtextureheight = bloomtextureheight;
5685 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5686 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5689 // when doing a reduced render (HDR) we want to use a smaller area
5690 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5691 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5692 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5693 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5694 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5696 // set up a texcoord array for the full resolution screen image
5697 // (we have to keep this around to copy back during final render)
5698 r_bloomstate.screentexcoord2f[0] = 0;
5699 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5700 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5701 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5702 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5703 r_bloomstate.screentexcoord2f[5] = 0;
5704 r_bloomstate.screentexcoord2f[6] = 0;
5705 r_bloomstate.screentexcoord2f[7] = 0;
5707 // set up a texcoord array for the reduced resolution bloom image
5708 // (which will be additive blended over the screen image)
5709 r_bloomstate.bloomtexcoord2f[0] = 0;
5710 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5711 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5712 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5713 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5714 r_bloomstate.bloomtexcoord2f[5] = 0;
5715 r_bloomstate.bloomtexcoord2f[6] = 0;
5716 r_bloomstate.bloomtexcoord2f[7] = 0;
5718 switch(vid.renderpath)
5720 case RENDERPATH_GL11:
5721 case RENDERPATH_GL13:
5722 case RENDERPATH_GL20:
5723 case RENDERPATH_SOFT:
5724 case RENDERPATH_GLES2:
5726 case RENDERPATH_D3D9:
5727 case RENDERPATH_D3D10:
5728 case RENDERPATH_D3D11:
5731 for (i = 0;i < 4;i++)
5733 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5734 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5735 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5736 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5742 if (r_hdr.integer || r_bloom.integer)
5744 r_bloomstate.enabled = true;
5745 r_bloomstate.hdr = r_hdr.integer != 0;
5748 R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
5751 void R_Bloom_CopyBloomTexture(float colorscale)
5753 r_refdef.stats.bloom++;
5755 // scale down screen texture to the bloom texture size
5757 R_SetViewport(&r_bloomstate.viewport);
5758 GL_BlendFunc(GL_ONE, GL_ZERO);
5759 GL_Color(colorscale, colorscale, colorscale, 1);
5760 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
5761 switch(vid.renderpath)
5763 case RENDERPATH_GL11:
5764 case RENDERPATH_GL13:
5765 case RENDERPATH_GL20:
5766 case RENDERPATH_SOFT:
5767 case RENDERPATH_GLES2:
5768 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5770 case RENDERPATH_D3D9:
5771 case RENDERPATH_D3D10:
5772 case RENDERPATH_D3D11:
5773 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5776 // TODO: do boxfilter scale-down in shader?
5777 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5778 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5779 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5781 // we now have a bloom image in the framebuffer
5782 // copy it into the bloom image texture for later processing
5783 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5784 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5787 void R_Bloom_CopyHDRTexture(void)
5789 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5790 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5793 void R_Bloom_MakeTexture(void)
5796 float xoffset, yoffset, r, brighten;
5798 r_refdef.stats.bloom++;
5800 R_ResetViewRendering2D();
5802 // we have a bloom image in the framebuffer
5804 R_SetViewport(&r_bloomstate.viewport);
5806 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5809 r = bound(0, r_bloom_colorexponent.value / x, 1);
5810 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5812 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5813 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5814 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5815 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5817 // copy the vertically blurred bloom view to a texture
5818 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5819 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5822 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5823 brighten = r_bloom_brighten.value;
5825 brighten *= r_hdr_range.value;
5826 brighten = sqrt(brighten);
5828 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5829 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5831 for (dir = 0;dir < 2;dir++)
5833 // blend on at multiple vertical offsets to achieve a vertical blur
5834 // TODO: do offset blends using GLSL
5835 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5836 GL_BlendFunc(GL_ONE, GL_ZERO);
5837 for (x = -range;x <= range;x++)
5839 if (!dir){xoffset = 0;yoffset = x;}
5840 else {xoffset = x;yoffset = 0;}
5841 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5842 yoffset /= (float)r_bloomstate.bloomtextureheight;
5843 // compute a texcoord array with the specified x and y offset
5844 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5845 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5846 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5847 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5848 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5849 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5850 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5851 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5852 // this r value looks like a 'dot' particle, fading sharply to
5853 // black at the edges
5854 // (probably not realistic but looks good enough)
5855 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5856 //r = brighten/(range*2+1);
5857 r = brighten / (range * 2 + 1);
5859 r *= (1 - x*x/(float)(range*range));
5860 GL_Color(r, r, r, 1);
5861 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5862 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5863 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5864 GL_BlendFunc(GL_ONE, GL_ONE);
5867 // copy the vertically blurred bloom view to a texture
5868 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5869 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5873 void R_HDR_RenderBloomTexture(void)
5875 int oldwidth, oldheight;
5876 float oldcolorscale;
5877 qboolean oldwaterstate;
5879 oldwaterstate = r_waterstate.enabled;
5880 oldcolorscale = r_refdef.view.colorscale;
5881 oldwidth = r_refdef.view.width;
5882 oldheight = r_refdef.view.height;
5883 r_refdef.view.width = r_bloomstate.bloomwidth;
5884 r_refdef.view.height = r_bloomstate.bloomheight;
5886 if(r_hdr.integer < 2)
5887 r_waterstate.enabled = false;
5889 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5890 // TODO: add exposure compensation features
5891 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5893 r_refdef.view.showdebug = false;
5894 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5896 R_ResetViewRendering3D();
5898 R_ClearScreen(r_refdef.fogenabled);
5899 if (r_timereport_active)
5900 R_TimeReport("HDRclear");
5903 if (r_timereport_active)
5904 R_TimeReport("visibility");
5906 // only do secondary renders with HDR if r_hdr is 2 or higher
5907 r_waterstate.numwaterplanes = 0;
5908 if (r_waterstate.enabled)
5909 R_RenderWaterPlanes();
5911 r_refdef.view.showdebug = true;
5913 r_waterstate.numwaterplanes = 0;
5915 R_ResetViewRendering2D();
5917 R_Bloom_CopyHDRTexture();
5918 R_Bloom_MakeTexture();
5920 // restore the view settings
5921 r_waterstate.enabled = oldwaterstate;
5922 r_refdef.view.width = oldwidth;
5923 r_refdef.view.height = oldheight;
5924 r_refdef.view.colorscale = oldcolorscale;
5926 R_ResetViewRendering3D();
5928 R_ClearScreen(r_refdef.fogenabled);
5929 if (r_timereport_active)
5930 R_TimeReport("viewclear");
5933 static void R_BlendView(void)
5935 unsigned int permutation;
5936 float uservecs[4][4];
5938 switch (vid.renderpath)
5940 case RENDERPATH_GL20:
5941 case RENDERPATH_D3D9:
5942 case RENDERPATH_D3D10:
5943 case RENDERPATH_D3D11:
5944 case RENDERPATH_SOFT:
5945 case RENDERPATH_GLES2:
5947 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5948 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5949 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5950 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5951 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5953 if (r_bloomstate.texture_screen)
5955 // make sure the buffer is available
5956 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5958 R_ResetViewRendering2D();
5960 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5962 // declare variables
5964 static float avgspeed;
5966 speed = VectorLength(cl.movement_velocity);
5968 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5969 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5971 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5972 speed = bound(0, speed, 1);
5973 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5975 // calculate values into a standard alpha
5976 cl.motionbluralpha = 1 - exp(-
5978 (r_motionblur.value * speed / 80)
5980 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5983 max(0.0001, cl.time - cl.oldtime) // fps independent
5986 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5987 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5989 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
5991 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5992 GL_Color(1, 1, 1, cl.motionbluralpha);
5993 switch(vid.renderpath)
5995 case RENDERPATH_GL11:
5996 case RENDERPATH_GL13:
5997 case RENDERPATH_GL20:
5998 case RENDERPATH_SOFT:
5999 case RENDERPATH_GLES2:
6000 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6002 case RENDERPATH_D3D9:
6003 case RENDERPATH_D3D10:
6004 case RENDERPATH_D3D11:
6005 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6008 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6009 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6010 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6014 // copy view into the screen texture
6015 R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6016 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6018 else if (!r_bloomstate.texture_bloom)
6020 // we may still have to do view tint...
6021 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6023 // apply a color tint to the whole view
6024 R_ResetViewRendering2D();
6025 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6026 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6027 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6028 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6029 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6031 break; // no screen processing, no bloom, skip it
6034 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6036 // render simple bloom effect
6037 // copy the screen and shrink it and darken it for the bloom process
6038 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6039 // make the bloom texture
6040 R_Bloom_MakeTexture();
6043 #if _MSC_VER >= 1400
6044 #define sscanf sscanf_s
6046 memset(uservecs, 0, sizeof(uservecs));
6047 if (r_glsl_postprocess_uservec1_enable.integer)
6048 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6049 if (r_glsl_postprocess_uservec2_enable.integer)
6050 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6051 if (r_glsl_postprocess_uservec3_enable.integer)
6052 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6053 if (r_glsl_postprocess_uservec4_enable.integer)
6054 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6056 R_ResetViewRendering2D();
6057 GL_Color(1, 1, 1, 1);
6058 GL_BlendFunc(GL_ONE, GL_ZERO);
6060 switch(vid.renderpath)
6062 case RENDERPATH_GL20:
6063 case RENDERPATH_GLES2:
6064 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6065 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6066 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6067 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6068 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6069 if (r_glsl_permutation->loc_ViewTintColor >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6070 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6071 if (r_glsl_permutation->loc_UserVec1 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6072 if (r_glsl_permutation->loc_UserVec2 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6073 if (r_glsl_permutation->loc_UserVec3 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6074 if (r_glsl_permutation->loc_UserVec4 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6075 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6076 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6077 if (r_glsl_permutation->loc_BloomColorSubtract >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6079 case RENDERPATH_D3D9:
6081 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6082 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6083 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6084 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6085 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6086 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6087 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6088 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6089 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6090 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6091 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6092 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6093 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6094 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6095 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6098 case RENDERPATH_D3D10:
6099 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6101 case RENDERPATH_D3D11:
6102 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6104 case RENDERPATH_SOFT:
6105 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6106 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6107 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6108 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6109 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6110 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6111 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6112 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6113 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6114 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6115 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6116 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6117 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6118 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6123 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6124 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6126 case RENDERPATH_GL13:
6127 case RENDERPATH_GL11:
6128 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6130 // apply a color tint to the whole view
6131 R_ResetViewRendering2D();
6132 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6133 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6134 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6135 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6136 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6142 matrix4x4_t r_waterscrollmatrix;
6144 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6146 if (r_refdef.fog_density)
6148 r_refdef.fogcolor[0] = r_refdef.fog_red;
6149 r_refdef.fogcolor[1] = r_refdef.fog_green;
6150 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6152 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6153 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6154 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6155 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6159 VectorCopy(r_refdef.fogcolor, fogvec);
6160 // color.rgb *= ContrastBoost * SceneBrightness;
6161 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6162 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6163 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6164 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6169 void R_UpdateVariables(void)
6173 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6175 r_refdef.farclip = r_farclip_base.value;
6176 if (r_refdef.scene.worldmodel)
6177 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6178 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6180 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6181 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6182 r_refdef.polygonfactor = 0;
6183 r_refdef.polygonoffset = 0;
6184 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6185 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6187 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6188 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6189 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6190 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6191 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6192 if (FAKELIGHT_ENABLED)
6194 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6196 if (r_showsurfaces.integer)
6198 r_refdef.scene.rtworld = false;
6199 r_refdef.scene.rtworldshadows = false;
6200 r_refdef.scene.rtdlight = false;
6201 r_refdef.scene.rtdlightshadows = false;
6202 r_refdef.lightmapintensity = 0;
6205 if (gamemode == GAME_NEHAHRA)
6207 if (gl_fogenable.integer)
6209 r_refdef.oldgl_fogenable = true;
6210 r_refdef.fog_density = gl_fogdensity.value;
6211 r_refdef.fog_red = gl_fogred.value;
6212 r_refdef.fog_green = gl_foggreen.value;
6213 r_refdef.fog_blue = gl_fogblue.value;
6214 r_refdef.fog_alpha = 1;
6215 r_refdef.fog_start = 0;
6216 r_refdef.fog_end = gl_skyclip.value;
6217 r_refdef.fog_height = 1<<30;
6218 r_refdef.fog_fadedepth = 128;
6220 else if (r_refdef.oldgl_fogenable)
6222 r_refdef.oldgl_fogenable = false;
6223 r_refdef.fog_density = 0;
6224 r_refdef.fog_red = 0;
6225 r_refdef.fog_green = 0;
6226 r_refdef.fog_blue = 0;
6227 r_refdef.fog_alpha = 0;
6228 r_refdef.fog_start = 0;
6229 r_refdef.fog_end = 0;
6230 r_refdef.fog_height = 1<<30;
6231 r_refdef.fog_fadedepth = 128;
6235 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6236 r_refdef.fog_start = max(0, r_refdef.fog_start);
6237 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6239 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6241 if (r_refdef.fog_density && r_drawfog.integer)
6243 r_refdef.fogenabled = true;
6244 // this is the point where the fog reaches 0.9986 alpha, which we
6245 // consider a good enough cutoff point for the texture
6246 // (0.9986 * 256 == 255.6)
6247 if (r_fog_exp2.integer)
6248 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6250 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6251 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6252 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6253 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6254 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6255 R_BuildFogHeightTexture();
6256 // fog color was already set
6257 // update the fog texture
6258 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
6259 R_BuildFogTexture();
6260 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6261 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6264 r_refdef.fogenabled = false;
6266 switch(vid.renderpath)
6268 case RENDERPATH_GL20:
6269 case RENDERPATH_D3D9:
6270 case RENDERPATH_D3D10:
6271 case RENDERPATH_D3D11:
6272 case RENDERPATH_SOFT:
6273 case RENDERPATH_GLES2:
6274 if(v_glslgamma.integer && !vid_gammatables_trivial)
6276 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6278 // build GLSL gamma texture
6279 #define RAMPWIDTH 256
6280 unsigned short ramp[RAMPWIDTH * 3];
6281 unsigned char rampbgr[RAMPWIDTH][4];
6284 r_texture_gammaramps_serial = vid_gammatables_serial;
6286 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6287 for(i = 0; i < RAMPWIDTH; ++i)
6289 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6290 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6291 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6294 if (r_texture_gammaramps)
6296 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6300 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6306 // remove GLSL gamma texture
6309 case RENDERPATH_GL13:
6310 case RENDERPATH_GL11:
6315 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6316 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6322 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6323 if( scenetype != r_currentscenetype ) {
6324 // store the old scenetype
6325 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6326 r_currentscenetype = scenetype;
6327 // move in the new scene
6328 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6337 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6339 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6340 if( scenetype == r_currentscenetype ) {
6341 return &r_refdef.scene;
6343 return &r_scenes_store[ scenetype ];
6352 int dpsoftrast_test;
6353 void R_RenderView(void)
6355 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6357 dpsoftrast_test = r_test.integer;
6359 if (r_timereport_active)
6360 R_TimeReport("start");
6361 r_textureframe++; // used only by R_GetCurrentTexture
6362 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6364 if(R_CompileShader_CheckStaticParms())
6367 if (!r_drawentities.integer)
6368 r_refdef.scene.numentities = 0;
6370 R_AnimCache_ClearCache();
6371 R_FrameData_NewFrame();
6373 /* adjust for stereo display */
6374 if(R_Stereo_Active())
6376 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
6377 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6380 if (r_refdef.view.isoverlay)
6382 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6383 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6384 R_TimeReport("depthclear");
6386 r_refdef.view.showdebug = false;
6388 r_waterstate.enabled = false;
6389 r_waterstate.numwaterplanes = 0;
6393 r_refdef.view.matrix = originalmatrix;
6399 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6401 r_refdef.view.matrix = originalmatrix;
6402 return; //Host_Error ("R_RenderView: NULL worldmodel");
6405 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6407 R_RenderView_UpdateViewVectors();
6409 R_Shadow_UpdateWorldLightSelection();
6411 R_Bloom_StartFrame();
6412 R_Water_StartFrame();
6415 if (r_timereport_active)
6416 R_TimeReport("viewsetup");
6418 R_ResetViewRendering3D();
6420 if (r_refdef.view.clear || r_refdef.fogenabled)
6422 R_ClearScreen(r_refdef.fogenabled);
6423 if (r_timereport_active)
6424 R_TimeReport("viewclear");
6426 r_refdef.view.clear = true;
6428 // this produces a bloom texture to be used in R_BlendView() later
6429 if (r_hdr.integer && r_bloomstate.bloomwidth)
6431 R_HDR_RenderBloomTexture();
6432 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6433 r_textureframe++; // used only by R_GetCurrentTexture
6436 r_refdef.view.showdebug = true;
6439 if (r_timereport_active)
6440 R_TimeReport("visibility");
6442 r_waterstate.numwaterplanes = 0;
6443 if (r_waterstate.enabled)
6444 R_RenderWaterPlanes();
6447 r_waterstate.numwaterplanes = 0;
6450 if (r_timereport_active)
6451 R_TimeReport("blendview");
6453 GL_Scissor(0, 0, vid.width, vid.height);
6454 GL_ScissorTest(false);
6456 r_refdef.view.matrix = originalmatrix;
6461 void R_RenderWaterPlanes(void)
6463 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6465 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6466 if (r_timereport_active)
6467 R_TimeReport("waterworld");
6470 // don't let sound skip if going slow
6471 if (r_refdef.scene.extraupdate)
6474 R_DrawModelsAddWaterPlanes();
6475 if (r_timereport_active)
6476 R_TimeReport("watermodels");
6478 if (r_waterstate.numwaterplanes)
6480 R_Water_ProcessPlanes();
6481 if (r_timereport_active)
6482 R_TimeReport("waterscenes");
6486 extern void R_DrawLightningBeams (void);
6487 extern void VM_CL_AddPolygonsToMeshQueue (void);
6488 extern void R_DrawPortals (void);
6489 extern cvar_t cl_locs_show;
6490 static void R_DrawLocs(void);
6491 static void R_DrawEntityBBoxes(void);
6492 static void R_DrawModelDecals(void);
6493 extern void R_DrawModelShadows(void);
6494 extern void R_DrawModelShadowMaps(void);
6495 extern cvar_t cl_decals_newsystem;
6496 extern qboolean r_shadow_usingdeferredprepass;
6497 void R_RenderScene(void)
6499 qboolean shadowmapping = false;
6501 if (r_timereport_active)
6502 R_TimeReport("beginscene");
6504 r_refdef.stats.renders++;
6508 // don't let sound skip if going slow
6509 if (r_refdef.scene.extraupdate)
6512 R_MeshQueue_BeginScene();
6516 Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
6518 if (r_timereport_active)
6519 R_TimeReport("skystartframe");
6521 if (cl.csqc_vidvars.drawworld)
6523 // don't let sound skip if going slow
6524 if (r_refdef.scene.extraupdate)
6527 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6529 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6530 if (r_timereport_active)
6531 R_TimeReport("worldsky");
6534 if (R_DrawBrushModelsSky() && r_timereport_active)
6535 R_TimeReport("bmodelsky");
6537 if (skyrendermasked && skyrenderlater)
6539 // we have to force off the water clipping plane while rendering sky
6543 if (r_timereport_active)
6544 R_TimeReport("sky");
6548 R_AnimCache_CacheVisibleEntities();
6549 if (r_timereport_active)
6550 R_TimeReport("animation");
6552 R_Shadow_PrepareLights();
6553 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6554 R_Shadow_PrepareModelShadows();
6555 if (r_timereport_active)
6556 R_TimeReport("preparelights");
6558 if (R_Shadow_ShadowMappingEnabled())
6559 shadowmapping = true;
6561 if (r_shadow_usingdeferredprepass)
6562 R_Shadow_DrawPrepass();
6564 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6566 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6567 if (r_timereport_active)
6568 R_TimeReport("worlddepth");
6570 if (r_depthfirst.integer >= 2)
6572 R_DrawModelsDepth();
6573 if (r_timereport_active)
6574 R_TimeReport("modeldepth");
6577 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6579 R_DrawModelShadowMaps();
6580 R_ResetViewRendering3D();
6581 // don't let sound skip if going slow
6582 if (r_refdef.scene.extraupdate)
6586 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6588 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6589 if (r_timereport_active)
6590 R_TimeReport("world");
6593 // don't let sound skip if going slow
6594 if (r_refdef.scene.extraupdate)
6598 if (r_timereport_active)
6599 R_TimeReport("models");
6601 // don't let sound skip if going slow
6602 if (r_refdef.scene.extraupdate)
6605 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6607 R_DrawModelShadows();
6608 R_ResetViewRendering3D();
6609 // don't let sound skip if going slow
6610 if (r_refdef.scene.extraupdate)
6614 if (!r_shadow_usingdeferredprepass)
6616 R_Shadow_DrawLights();
6617 if (r_timereport_active)
6618 R_TimeReport("rtlights");
6621 // don't let sound skip if going slow
6622 if (r_refdef.scene.extraupdate)
6625 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6627 R_DrawModelShadows();
6628 R_ResetViewRendering3D();
6629 // don't let sound skip if going slow
6630 if (r_refdef.scene.extraupdate)
6634 if (cl.csqc_vidvars.drawworld)
6636 if (cl_decals_newsystem.integer)
6638 R_DrawModelDecals();
6639 if (r_timereport_active)
6640 R_TimeReport("modeldecals");
6645 if (r_timereport_active)
6646 R_TimeReport("decals");
6650 if (r_timereport_active)
6651 R_TimeReport("particles");
6654 if (r_timereport_active)
6655 R_TimeReport("explosions");
6657 R_DrawLightningBeams();
6658 if (r_timereport_active)
6659 R_TimeReport("lightning");
6662 VM_CL_AddPolygonsToMeshQueue();
6664 if (r_refdef.view.showdebug)
6666 if (cl_locs_show.integer)
6669 if (r_timereport_active)
6670 R_TimeReport("showlocs");
6673 if (r_drawportals.integer)
6676 if (r_timereport_active)
6677 R_TimeReport("portals");
6680 if (r_showbboxes.value > 0)
6682 R_DrawEntityBBoxes();
6683 if (r_timereport_active)
6684 R_TimeReport("bboxes");
6688 R_MeshQueue_RenderTransparent();
6689 if (r_timereport_active)
6690 R_TimeReport("drawtrans");
6692 if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0))
6694 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6695 if (r_timereport_active)
6696 R_TimeReport("worlddebug");
6697 R_DrawModelsDebug();
6698 if (r_timereport_active)
6699 R_TimeReport("modeldebug");
6702 if (cl.csqc_vidvars.drawworld)
6704 R_Shadow_DrawCoronas();
6705 if (r_timereport_active)
6706 R_TimeReport("coronas");
6711 GL_DepthTest(false);
6712 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6713 GL_Color(1, 1, 1, 1);
6714 qglBegin(GL_POLYGON);
6715 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6716 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6717 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6718 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6720 qglBegin(GL_POLYGON);
6721 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
6722 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
6723 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
6724 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
6726 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6730 // don't let sound skip if going slow
6731 if (r_refdef.scene.extraupdate)
6734 R_ResetViewRendering2D();
6737 static const unsigned short bboxelements[36] =
6747 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6750 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6752 RSurf_ActiveWorldEntity();
6754 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6755 GL_DepthMask(false);
6756 GL_DepthRange(0, 1);
6757 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6758 // R_Mesh_ResetTextureState();
6760 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6761 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6762 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6763 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6764 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6765 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6766 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6767 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6768 R_FillColors(color4f, 8, cr, cg, cb, ca);
6769 if (r_refdef.fogenabled)
6771 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6773 f1 = RSurf_FogVertex(v);
6775 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6776 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6777 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6780 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6781 R_Mesh_ResetTextureState();
6782 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6783 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6786 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6790 prvm_edict_t *edict;
6791 prvm_prog_t *prog_save = prog;
6793 // this function draws bounding boxes of server entities
6797 GL_CullFace(GL_NONE);
6798 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6802 for (i = 0;i < numsurfaces;i++)
6804 edict = PRVM_EDICT_NUM(surfacelist[i]);
6805 switch ((int)edict->fields.server->solid)
6807 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6808 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6809 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6810 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6811 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6812 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6814 color[3] *= r_showbboxes.value;
6815 color[3] = bound(0, color[3], 1);
6816 GL_DepthTest(!r_showdisabledepthtest.integer);
6817 GL_CullFace(r_refdef.view.cullface_front);
6818 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6824 static void R_DrawEntityBBoxes(void)
6827 prvm_edict_t *edict;
6829 prvm_prog_t *prog_save = prog;
6831 // this function draws bounding boxes of server entities
6837 for (i = 0;i < prog->num_edicts;i++)
6839 edict = PRVM_EDICT_NUM(i);
6840 if (edict->priv.server->free)
6842 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6843 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6845 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6847 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6848 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6854 static const int nomodelelement3i[24] =
6866 static const unsigned short nomodelelement3s[24] =
6878 static const float nomodelvertex3f[6*3] =
6888 static const float nomodelcolor4f[6*4] =
6890 0.0f, 0.0f, 0.5f, 1.0f,
6891 0.0f, 0.0f, 0.5f, 1.0f,
6892 0.0f, 0.5f, 0.0f, 1.0f,
6893 0.0f, 0.5f, 0.0f, 1.0f,
6894 0.5f, 0.0f, 0.0f, 1.0f,
6895 0.5f, 0.0f, 0.0f, 1.0f
6898 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6904 RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
6906 // this is only called once per entity so numsurfaces is always 1, and
6907 // surfacelist is always {0}, so this code does not handle batches
6909 if (rsurface.ent_flags & RENDER_ADDITIVE)
6911 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6912 GL_DepthMask(false);
6914 else if (rsurface.colormod[3] < 1)
6916 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6917 GL_DepthMask(false);
6921 GL_BlendFunc(GL_ONE, GL_ZERO);
6924 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6925 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6926 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6927 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6928 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6929 for (i = 0, c = color4f;i < 6;i++, c += 4)
6931 c[0] *= rsurface.colormod[0];
6932 c[1] *= rsurface.colormod[1];
6933 c[2] *= rsurface.colormod[2];
6934 c[3] *= rsurface.colormod[3];
6936 if (r_refdef.fogenabled)
6938 for (i = 0, c = color4f;i < 6;i++, c += 4)
6940 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6942 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6943 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6944 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6947 // R_Mesh_ResetTextureState();
6948 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6949 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6950 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6953 void R_DrawNoModel(entity_render_t *ent)
6956 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6957 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6958 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6960 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6963 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6965 vec3_t right1, right2, diff, normal;
6967 VectorSubtract (org2, org1, normal);
6969 // calculate 'right' vector for start
6970 VectorSubtract (r_refdef.view.origin, org1, diff);
6971 CrossProduct (normal, diff, right1);
6972 VectorNormalize (right1);
6974 // calculate 'right' vector for end
6975 VectorSubtract (r_refdef.view.origin, org2, diff);
6976 CrossProduct (normal, diff, right2);
6977 VectorNormalize (right2);
6979 vert[ 0] = org1[0] + width * right1[0];
6980 vert[ 1] = org1[1] + width * right1[1];
6981 vert[ 2] = org1[2] + width * right1[2];
6982 vert[ 3] = org1[0] - width * right1[0];
6983 vert[ 4] = org1[1] - width * right1[1];
6984 vert[ 5] = org1[2] - width * right1[2];
6985 vert[ 6] = org2[0] - width * right2[0];
6986 vert[ 7] = org2[1] - width * right2[1];
6987 vert[ 8] = org2[2] - width * right2[2];
6988 vert[ 9] = org2[0] + width * right2[0];
6989 vert[10] = org2[1] + width * right2[1];
6990 vert[11] = org2[2] + width * right2[2];
6993 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
6995 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6996 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6997 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6998 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6999 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7000 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7001 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7002 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7003 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7004 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7005 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7006 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7009 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7014 VectorSet(v, x, y, z);
7015 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7016 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7018 if (i == mesh->numvertices)
7020 if (mesh->numvertices < mesh->maxvertices)
7022 VectorCopy(v, vertex3f);
7023 mesh->numvertices++;
7025 return mesh->numvertices;
7031 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7035 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7036 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7037 e = mesh->element3i + mesh->numtriangles * 3;
7038 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7040 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7041 if (mesh->numtriangles < mesh->maxtriangles)
7046 mesh->numtriangles++;
7048 element[1] = element[2];
7052 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7056 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7057 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7058 e = mesh->element3i + mesh->numtriangles * 3;
7059 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7061 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7062 if (mesh->numtriangles < mesh->maxtriangles)
7067 mesh->numtriangles++;
7069 element[1] = element[2];
7073 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7074 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7076 int planenum, planenum2;
7079 mplane_t *plane, *plane2;
7081 double temppoints[2][256*3];
7082 // figure out how large a bounding box we need to properly compute this brush
7084 for (w = 0;w < numplanes;w++)
7085 maxdist = max(maxdist, fabs(planes[w].dist));
7086 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7087 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7088 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7092 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7093 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7095 if (planenum2 == planenum)
7097 PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
7100 if (tempnumpoints < 3)
7102 // generate elements forming a triangle fan for this polygon
7103 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7107 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
7109 texturelayer_t *layer;
7110 layer = t->currentlayers + t->currentnumlayers++;
7112 layer->depthmask = depthmask;
7113 layer->blendfunc1 = blendfunc1;
7114 layer->blendfunc2 = blendfunc2;
7115 layer->texture = texture;
7116 layer->texmatrix = *matrix;
7117 layer->color[0] = r;
7118 layer->color[1] = g;
7119 layer->color[2] = b;
7120 layer->color[3] = a;
7123 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7125 if(parms[0] == 0 && parms[1] == 0)
7127 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7128 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7133 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7136 index = parms[2] + r_refdef.scene.time * parms[3];
7137 index -= floor(index);
7138 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7141 case Q3WAVEFUNC_NONE:
7142 case Q3WAVEFUNC_NOISE:
7143 case Q3WAVEFUNC_COUNT:
7146 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7147 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7148 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7149 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7150 case Q3WAVEFUNC_TRIANGLE:
7152 f = index - floor(index);
7163 f = parms[0] + parms[1] * f;
7164 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7165 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7169 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7174 matrix4x4_t matrix, temp;
7175 switch(tcmod->tcmod)
7179 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7180 matrix = r_waterscrollmatrix;
7182 matrix = identitymatrix;
7184 case Q3TCMOD_ENTITYTRANSLATE:
7185 // this is used in Q3 to allow the gamecode to control texcoord
7186 // scrolling on the entity, which is not supported in darkplaces yet.
7187 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7189 case Q3TCMOD_ROTATE:
7190 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7191 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7192 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7195 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7197 case Q3TCMOD_SCROLL:
7198 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7200 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7201 w = (int) tcmod->parms[0];
7202 h = (int) tcmod->parms[1];
7203 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7205 idx = (int) floor(f * w * h);
7206 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7208 case Q3TCMOD_STRETCH:
7209 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7210 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7212 case Q3TCMOD_TRANSFORM:
7213 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7214 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7215 VectorSet(tcmat + 6, 0 , 0 , 1);
7216 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7217 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7219 case Q3TCMOD_TURBULENT:
7220 // this is handled in the RSurf_PrepareVertices function
7221 matrix = identitymatrix;
7225 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7228 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7230 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7231 char name[MAX_QPATH];
7232 skinframe_t *skinframe;
7233 unsigned char pixels[296*194];
7234 strlcpy(cache->name, skinname, sizeof(cache->name));
7235 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7236 if (developer_loading.integer)
7237 Con_Printf("loading %s\n", name);
7238 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7239 if (!skinframe || !skinframe->base)
7242 fs_offset_t filesize;
7244 f = FS_LoadFile(name, tempmempool, true, &filesize);
7247 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7248 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7252 cache->skinframe = skinframe;
7255 texture_t *R_GetCurrentTexture(texture_t *t)
7258 const entity_render_t *ent = rsurface.entity;
7259 dp_model_t *model = ent->model;
7260 q3shaderinfo_layer_tcmod_t *tcmod;
7262 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7263 return t->currentframe;
7264 t->update_lastrenderframe = r_textureframe;
7265 t->update_lastrenderentity = (void *)ent;
7267 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7268 t->camera_entity = ent->entitynumber;
7270 t->camera_entity = 0;
7272 // switch to an alternate material if this is a q1bsp animated material
7274 texture_t *texture = t;
7275 int s = rsurface.ent_skinnum;
7276 if ((unsigned int)s >= (unsigned int)model->numskins)
7278 if (model->skinscenes)
7280 if (model->skinscenes[s].framecount > 1)
7281 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7283 s = model->skinscenes[s].firstframe;
7286 t = t + s * model->num_surfaces;
7289 // use an alternate animation if the entity's frame is not 0,
7290 // and only if the texture has an alternate animation
7291 if (rsurface.ent_alttextures && t->anim_total[1])
7292 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7294 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7296 texture->currentframe = t;
7299 // update currentskinframe to be a qw skin or animation frame
7300 if (rsurface.ent_qwskin >= 0)
7302 i = rsurface.ent_qwskin;
7303 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7305 r_qwskincache_size = cl.maxclients;
7307 Mem_Free(r_qwskincache);
7308 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7310 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7311 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7312 t->currentskinframe = r_qwskincache[i].skinframe;
7313 if (t->currentskinframe == NULL)
7314 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7316 else if (t->numskinframes >= 2)
7317 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7318 if (t->backgroundnumskinframes >= 2)
7319 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7321 t->currentmaterialflags = t->basematerialflags;
7322 t->currentalpha = rsurface.colormod[3];
7323 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7324 t->currentalpha *= r_wateralpha.value;
7325 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7326 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7327 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7328 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7329 if (!(rsurface.ent_flags & RENDER_LIGHT))
7330 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7331 else if (FAKELIGHT_ENABLED)
7333 // no modellight if using fakelight for the map
7335 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7337 // pick a model lighting mode
7338 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7339 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7341 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7343 if (rsurface.ent_flags & RENDER_ADDITIVE)
7344 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7345 else if (t->currentalpha < 1)
7346 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7347 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7348 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7349 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7350 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7351 if (t->backgroundnumskinframes)
7352 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7353 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7355 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7356 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7359 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7360 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7361 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7363 // there is no tcmod
7364 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7366 t->currenttexmatrix = r_waterscrollmatrix;
7367 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7369 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7371 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7372 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7375 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7376 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7377 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7378 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7380 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7381 if (t->currentskinframe->qpixels)
7382 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7383 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7384 if (!t->basetexture)
7385 t->basetexture = r_texture_notexture;
7386 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7387 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7388 t->nmaptexture = t->currentskinframe->nmap;
7389 if (!t->nmaptexture)
7390 t->nmaptexture = r_texture_blanknormalmap;
7391 t->glosstexture = r_texture_black;
7392 t->glowtexture = t->currentskinframe->glow;
7393 t->fogtexture = t->currentskinframe->fog;
7394 t->reflectmasktexture = t->currentskinframe->reflect;
7395 if (t->backgroundnumskinframes)
7397 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7398 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7399 t->backgroundglosstexture = r_texture_black;
7400 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7401 if (!t->backgroundnmaptexture)
7402 t->backgroundnmaptexture = r_texture_blanknormalmap;
7406 t->backgroundbasetexture = r_texture_white;
7407 t->backgroundnmaptexture = r_texture_blanknormalmap;
7408 t->backgroundglosstexture = r_texture_black;
7409 t->backgroundglowtexture = NULL;
7411 t->specularpower = r_shadow_glossexponent.value;
7412 // TODO: store reference values for these in the texture?
7413 t->specularscale = 0;
7414 if (r_shadow_gloss.integer > 0)
7416 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7418 if (r_shadow_glossintensity.value > 0)
7420 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7421 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7422 t->specularscale = r_shadow_glossintensity.value;
7425 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7427 t->glosstexture = r_texture_white;
7428 t->backgroundglosstexture = r_texture_white;
7429 t->specularscale = r_shadow_gloss2intensity.value;
7430 t->specularpower = r_shadow_gloss2exponent.value;
7433 t->specularscale *= t->specularscalemod;
7434 t->specularpower *= t->specularpowermod;
7436 // lightmaps mode looks bad with dlights using actual texturing, so turn
7437 // off the colormap and glossmap, but leave the normalmap on as it still
7438 // accurately represents the shading involved
7439 if (gl_lightmaps.integer)
7441 t->basetexture = r_texture_grey128;
7442 t->pantstexture = r_texture_black;
7443 t->shirttexture = r_texture_black;
7444 t->nmaptexture = r_texture_blanknormalmap;
7445 t->glosstexture = r_texture_black;
7446 t->glowtexture = NULL;
7447 t->fogtexture = NULL;
7448 t->reflectmasktexture = NULL;
7449 t->backgroundbasetexture = NULL;
7450 t->backgroundnmaptexture = r_texture_blanknormalmap;
7451 t->backgroundglosstexture = r_texture_black;
7452 t->backgroundglowtexture = NULL;
7453 t->specularscale = 0;
7454 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7457 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7458 VectorClear(t->dlightcolor);
7459 t->currentnumlayers = 0;
7460 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7462 int blendfunc1, blendfunc2;
7464 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7466 blendfunc1 = GL_SRC_ALPHA;
7467 blendfunc2 = GL_ONE;
7469 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7471 blendfunc1 = GL_SRC_ALPHA;
7472 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7474 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7476 blendfunc1 = t->customblendfunc[0];
7477 blendfunc2 = t->customblendfunc[1];
7481 blendfunc1 = GL_ONE;
7482 blendfunc2 = GL_ZERO;
7484 // don't colormod evilblend textures
7485 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7486 VectorSet(t->lightmapcolor, 1, 1, 1);
7487 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7488 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7490 // fullbright is not affected by r_refdef.lightmapintensity
7491 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
7492 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7493 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
7494 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7495 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
7499 vec3_t ambientcolor;
7501 // set the color tint used for lights affecting this surface
7502 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7504 // q3bsp has no lightmap updates, so the lightstylevalue that
7505 // would normally be baked into the lightmap must be
7506 // applied to the color
7507 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7508 if (model->type == mod_brushq3)
7509 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7510 colorscale *= r_refdef.lightmapintensity;
7511 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7512 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7513 // basic lit geometry
7514 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
7515 // add pants/shirt if needed
7516 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7517 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
7518 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7519 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
7520 // now add ambient passes if needed
7521 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7523 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
7524 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7525 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
7526 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7527 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
7530 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7531 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
7532 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7534 // if this is opaque use alpha blend which will darken the earlier
7537 // if this is an alpha blended material, all the earlier passes
7538 // were darkened by fog already, so we only need to add the fog
7539 // color ontop through the fog mask texture
7541 // if this is an additive blended material, all the earlier passes
7542 // were darkened by fog already, and we should not add fog color
7543 // (because the background was not darkened, there is no fog color
7544 // that was lost behind it).
7545 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
7549 return t->currentframe;
7552 rsurfacestate_t rsurface;
7554 void RSurf_ActiveWorldEntity(void)
7556 dp_model_t *model = r_refdef.scene.worldmodel;
7557 //if (rsurface.entity == r_refdef.scene.worldentity)
7559 rsurface.entity = r_refdef.scene.worldentity;
7560 rsurface.skeleton = NULL;
7561 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7562 rsurface.ent_skinnum = 0;
7563 rsurface.ent_qwskin = -1;
7564 rsurface.ent_shadertime = 0;
7565 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7566 rsurface.matrix = identitymatrix;
7567 rsurface.inversematrix = identitymatrix;
7568 rsurface.matrixscale = 1;
7569 rsurface.inversematrixscale = 1;
7570 R_EntityMatrix(&identitymatrix);
7571 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7572 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7573 rsurface.fograngerecip = r_refdef.fograngerecip;
7574 rsurface.fogheightfade = r_refdef.fogheightfade;
7575 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7576 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7577 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7578 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7579 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7580 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7581 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7582 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7583 rsurface.colormod[3] = 1;
7584 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
7585 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7586 rsurface.frameblend[0].lerp = 1;
7587 rsurface.ent_alttextures = false;
7588 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7589 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7590 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7591 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7592 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7593 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7594 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7595 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7596 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7597 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7598 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7599 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7600 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7601 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7602 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7603 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7604 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7605 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7606 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7607 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7608 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7609 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7610 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7611 rsurface.modelelement3i = model->surfmesh.data_element3i;
7612 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7613 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7614 rsurface.modelelement3s = model->surfmesh.data_element3s;
7615 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7616 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7617 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7618 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7619 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7620 rsurface.modelsurfaces = model->data_surfaces;
7621 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7622 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7623 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7624 rsurface.modelgeneratedvertex = false;
7625 rsurface.batchgeneratedvertex = false;
7626 rsurface.batchfirstvertex = 0;
7627 rsurface.batchnumvertices = 0;
7628 rsurface.batchfirsttriangle = 0;
7629 rsurface.batchnumtriangles = 0;
7630 rsurface.batchvertex3f = NULL;
7631 rsurface.batchvertex3f_vertexbuffer = NULL;
7632 rsurface.batchvertex3f_bufferoffset = 0;
7633 rsurface.batchsvector3f = NULL;
7634 rsurface.batchsvector3f_vertexbuffer = NULL;
7635 rsurface.batchsvector3f_bufferoffset = 0;
7636 rsurface.batchtvector3f = NULL;
7637 rsurface.batchtvector3f_vertexbuffer = NULL;
7638 rsurface.batchtvector3f_bufferoffset = 0;
7639 rsurface.batchnormal3f = NULL;
7640 rsurface.batchnormal3f_vertexbuffer = NULL;
7641 rsurface.batchnormal3f_bufferoffset = 0;
7642 rsurface.batchlightmapcolor4f = NULL;
7643 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7644 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7645 rsurface.batchtexcoordtexture2f = NULL;
7646 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7647 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7648 rsurface.batchtexcoordlightmap2f = NULL;
7649 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7650 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7651 rsurface.batchvertexmesh = NULL;
7652 rsurface.batchvertexmeshbuffer = NULL;
7653 rsurface.batchvertex3fbuffer = NULL;
7654 rsurface.batchelement3i = NULL;
7655 rsurface.batchelement3i_indexbuffer = NULL;
7656 rsurface.batchelement3i_bufferoffset = 0;
7657 rsurface.batchelement3s = NULL;
7658 rsurface.batchelement3s_indexbuffer = NULL;
7659 rsurface.batchelement3s_bufferoffset = 0;
7660 rsurface.passcolor4f = NULL;
7661 rsurface.passcolor4f_vertexbuffer = NULL;
7662 rsurface.passcolor4f_bufferoffset = 0;
7665 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7667 dp_model_t *model = ent->model;
7668 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7670 rsurface.entity = (entity_render_t *)ent;
7671 rsurface.skeleton = ent->skeleton;
7672 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7673 rsurface.ent_skinnum = ent->skinnum;
7674 rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
7675 rsurface.ent_shadertime = ent->shadertime;
7676 rsurface.ent_flags = ent->flags;
7677 rsurface.matrix = ent->matrix;
7678 rsurface.inversematrix = ent->inversematrix;
7679 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7680 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7681 R_EntityMatrix(&rsurface.matrix);
7682 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7683 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7684 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7685 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7686 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7687 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7688 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7689 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7690 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7691 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7692 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7693 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7694 rsurface.colormod[3] = ent->alpha;
7695 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7696 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7697 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7698 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7699 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7700 if (ent->model->brush.submodel && !prepass)
7702 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7703 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7705 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7707 if (ent->animcache_vertex3f)
7709 rsurface.modelvertex3f = ent->animcache_vertex3f;
7710 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7711 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7712 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7713 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7714 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7715 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7717 else if (wanttangents)
7719 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7720 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7721 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7722 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7723 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7724 rsurface.modelvertexmesh = NULL;
7725 rsurface.modelvertexmeshbuffer = NULL;
7726 rsurface.modelvertex3fbuffer = NULL;
7728 else if (wantnormals)
7730 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7731 rsurface.modelsvector3f = NULL;
7732 rsurface.modeltvector3f = NULL;
7733 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7734 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7735 rsurface.modelvertexmesh = NULL;
7736 rsurface.modelvertexmeshbuffer = NULL;
7737 rsurface.modelvertex3fbuffer = NULL;
7741 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7742 rsurface.modelsvector3f = NULL;
7743 rsurface.modeltvector3f = NULL;
7744 rsurface.modelnormal3f = NULL;
7745 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7746 rsurface.modelvertexmesh = NULL;
7747 rsurface.modelvertexmeshbuffer = NULL;
7748 rsurface.modelvertex3fbuffer = NULL;
7750 rsurface.modelvertex3f_vertexbuffer = 0;
7751 rsurface.modelvertex3f_bufferoffset = 0;
7752 rsurface.modelsvector3f_vertexbuffer = 0;
7753 rsurface.modelsvector3f_bufferoffset = 0;
7754 rsurface.modeltvector3f_vertexbuffer = 0;
7755 rsurface.modeltvector3f_bufferoffset = 0;
7756 rsurface.modelnormal3f_vertexbuffer = 0;
7757 rsurface.modelnormal3f_bufferoffset = 0;
7758 rsurface.modelgeneratedvertex = true;
7762 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7763 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7764 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7765 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7766 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7767 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7768 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7769 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7770 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7771 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7772 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7773 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7774 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7775 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7776 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7777 rsurface.modelgeneratedvertex = false;
7779 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7780 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7781 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7782 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7783 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7784 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7785 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7786 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7787 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7788 rsurface.modelelement3i = model->surfmesh.data_element3i;
7789 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7790 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7791 rsurface.modelelement3s = model->surfmesh.data_element3s;
7792 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7793 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7794 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7795 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7796 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7797 rsurface.modelsurfaces = model->data_surfaces;
7798 rsurface.batchgeneratedvertex = false;
7799 rsurface.batchfirstvertex = 0;
7800 rsurface.batchnumvertices = 0;
7801 rsurface.batchfirsttriangle = 0;
7802 rsurface.batchnumtriangles = 0;
7803 rsurface.batchvertex3f = NULL;
7804 rsurface.batchvertex3f_vertexbuffer = NULL;
7805 rsurface.batchvertex3f_bufferoffset = 0;
7806 rsurface.batchsvector3f = NULL;
7807 rsurface.batchsvector3f_vertexbuffer = NULL;
7808 rsurface.batchsvector3f_bufferoffset = 0;
7809 rsurface.batchtvector3f = NULL;
7810 rsurface.batchtvector3f_vertexbuffer = NULL;
7811 rsurface.batchtvector3f_bufferoffset = 0;
7812 rsurface.batchnormal3f = NULL;
7813 rsurface.batchnormal3f_vertexbuffer = NULL;
7814 rsurface.batchnormal3f_bufferoffset = 0;
7815 rsurface.batchlightmapcolor4f = NULL;
7816 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7817 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7818 rsurface.batchtexcoordtexture2f = NULL;
7819 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7820 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7821 rsurface.batchtexcoordlightmap2f = NULL;
7822 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7823 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7824 rsurface.batchvertexmesh = NULL;
7825 rsurface.batchvertexmeshbuffer = NULL;
7826 rsurface.batchvertex3fbuffer = NULL;
7827 rsurface.batchelement3i = NULL;
7828 rsurface.batchelement3i_indexbuffer = NULL;
7829 rsurface.batchelement3i_bufferoffset = 0;
7830 rsurface.batchelement3s = NULL;
7831 rsurface.batchelement3s_indexbuffer = NULL;
7832 rsurface.batchelement3s_bufferoffset = 0;
7833 rsurface.passcolor4f = NULL;
7834 rsurface.passcolor4f_vertexbuffer = NULL;
7835 rsurface.passcolor4f_bufferoffset = 0;
7838 void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
7840 rsurface.entity = r_refdef.scene.worldentity;
7841 rsurface.skeleton = NULL;
7842 rsurface.ent_skinnum = 0;
7843 rsurface.ent_qwskin = -1;
7844 rsurface.ent_shadertime = shadertime;
7845 rsurface.ent_flags = entflags;
7846 rsurface.modelnumvertices = numvertices;
7847 rsurface.modelnumtriangles = numtriangles;
7848 rsurface.matrix = *matrix;
7849 rsurface.inversematrix = *inversematrix;
7850 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7851 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7852 R_EntityMatrix(&rsurface.matrix);
7853 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7854 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7855 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7856 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7857 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7858 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7859 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7860 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7861 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7862 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7863 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7864 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7865 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
7866 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7867 rsurface.frameblend[0].lerp = 1;
7868 rsurface.ent_alttextures = false;
7869 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7870 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7873 rsurface.modelvertex3f = (float *)vertex3f;
7874 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7875 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7876 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7878 else if (wantnormals)
7880 rsurface.modelvertex3f = (float *)vertex3f;
7881 rsurface.modelsvector3f = NULL;
7882 rsurface.modeltvector3f = NULL;
7883 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7887 rsurface.modelvertex3f = (float *)vertex3f;
7888 rsurface.modelsvector3f = NULL;
7889 rsurface.modeltvector3f = NULL;
7890 rsurface.modelnormal3f = NULL;
7892 rsurface.modelvertexmesh = NULL;
7893 rsurface.modelvertexmeshbuffer = NULL;
7894 rsurface.modelvertex3fbuffer = NULL;
7895 rsurface.modelvertex3f_vertexbuffer = 0;
7896 rsurface.modelvertex3f_bufferoffset = 0;
7897 rsurface.modelsvector3f_vertexbuffer = 0;
7898 rsurface.modelsvector3f_bufferoffset = 0;
7899 rsurface.modeltvector3f_vertexbuffer = 0;
7900 rsurface.modeltvector3f_bufferoffset = 0;
7901 rsurface.modelnormal3f_vertexbuffer = 0;
7902 rsurface.modelnormal3f_bufferoffset = 0;
7903 rsurface.modelgeneratedvertex = true;
7904 rsurface.modellightmapcolor4f = (float *)color4f;
7905 rsurface.modellightmapcolor4f_vertexbuffer = 0;
7906 rsurface.modellightmapcolor4f_bufferoffset = 0;
7907 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
7908 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7909 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7910 rsurface.modeltexcoordlightmap2f = NULL;
7911 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7912 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7913 rsurface.modelelement3i = (int *)element3i;
7914 rsurface.modelelement3i_indexbuffer = NULL;
7915 rsurface.modelelement3i_bufferoffset = 0;
7916 rsurface.modelelement3s = (unsigned short *)element3s;
7917 rsurface.modelelement3s_indexbuffer = NULL;
7918 rsurface.modelelement3s_bufferoffset = 0;
7919 rsurface.modellightmapoffsets = NULL;
7920 rsurface.modelsurfaces = NULL;
7921 rsurface.batchgeneratedvertex = false;
7922 rsurface.batchfirstvertex = 0;
7923 rsurface.batchnumvertices = 0;
7924 rsurface.batchfirsttriangle = 0;
7925 rsurface.batchnumtriangles = 0;
7926 rsurface.batchvertex3f = NULL;
7927 rsurface.batchvertex3f_vertexbuffer = NULL;
7928 rsurface.batchvertex3f_bufferoffset = 0;
7929 rsurface.batchsvector3f = NULL;
7930 rsurface.batchsvector3f_vertexbuffer = NULL;
7931 rsurface.batchsvector3f_bufferoffset = 0;
7932 rsurface.batchtvector3f = NULL;
7933 rsurface.batchtvector3f_vertexbuffer = NULL;
7934 rsurface.batchtvector3f_bufferoffset = 0;
7935 rsurface.batchnormal3f = NULL;
7936 rsurface.batchnormal3f_vertexbuffer = NULL;
7937 rsurface.batchnormal3f_bufferoffset = 0;
7938 rsurface.batchlightmapcolor4f = NULL;
7939 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7940 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7941 rsurface.batchtexcoordtexture2f = NULL;
7942 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7943 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7944 rsurface.batchtexcoordlightmap2f = NULL;
7945 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7946 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7947 rsurface.batchvertexmesh = NULL;
7948 rsurface.batchvertexmeshbuffer = NULL;
7949 rsurface.batchvertex3fbuffer = NULL;
7950 rsurface.batchelement3i = NULL;
7951 rsurface.batchelement3i_indexbuffer = NULL;
7952 rsurface.batchelement3i_bufferoffset = 0;
7953 rsurface.batchelement3s = NULL;
7954 rsurface.batchelement3s_indexbuffer = NULL;
7955 rsurface.batchelement3s_bufferoffset = 0;
7956 rsurface.passcolor4f = NULL;
7957 rsurface.passcolor4f_vertexbuffer = NULL;
7958 rsurface.passcolor4f_bufferoffset = 0;
7960 if (rsurface.modelnumvertices && rsurface.modelelement3i)
7962 if ((wantnormals || wanttangents) && !normal3f)
7964 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7965 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7967 if (wanttangents && !svector3f)
7969 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7970 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7971 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7976 float RSurf_FogPoint(const float *v)
7978 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7979 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7980 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7981 float FogHeightFade = r_refdef.fogheightfade;
7983 unsigned int fogmasktableindex;
7984 if (r_refdef.fogplaneviewabove)
7985 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7987 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7988 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7989 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7992 float RSurf_FogVertex(const float *v)
7994 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7995 float FogPlaneViewDist = rsurface.fogplaneviewdist;
7996 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7997 float FogHeightFade = rsurface.fogheightfade;
7999 unsigned int fogmasktableindex;
8000 if (r_refdef.fogplaneviewabove)
8001 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8003 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8004 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8005 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8008 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8011 for (i = 0;i < numelements;i++)
8012 outelement3i[i] = inelement3i[i] + adjust;
8015 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8016 extern cvar_t gl_vbo;
8017 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8025 int surfacefirsttriangle;
8026 int surfacenumtriangles;
8027 int surfacefirstvertex;
8028 int surfaceendvertex;
8029 int surfacenumvertices;
8030 int batchnumvertices;
8031 int batchnumtriangles;
8035 qboolean dynamicvertex;
8039 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8041 q3shaderinfo_deform_t *deform;
8042 const msurface_t *surface, *firstsurface;
8043 r_vertexmesh_t *vertexmesh;
8044 if (!texturenumsurfaces)
8046 // find vertex range of this surface batch
8048 firstsurface = texturesurfacelist[0];
8049 firsttriangle = firstsurface->num_firsttriangle;
8050 batchnumvertices = 0;
8051 batchnumtriangles = 0;
8052 firstvertex = endvertex = firstsurface->num_firstvertex;
8053 for (i = 0;i < texturenumsurfaces;i++)
8055 surface = texturesurfacelist[i];
8056 if (surface != firstsurface + i)
8058 surfacefirstvertex = surface->num_firstvertex;
8059 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8060 surfacenumvertices = surface->num_vertices;
8061 surfacenumtriangles = surface->num_triangles;
8062 if (firstvertex > surfacefirstvertex)
8063 firstvertex = surfacefirstvertex;
8064 if (endvertex < surfaceendvertex)
8065 endvertex = surfaceendvertex;
8066 batchnumvertices += surfacenumvertices;
8067 batchnumtriangles += surfacenumtriangles;
8070 // we now know the vertex range used, and if there are any gaps in it
8071 rsurface.batchfirstvertex = firstvertex;
8072 rsurface.batchnumvertices = endvertex - firstvertex;
8073 rsurface.batchfirsttriangle = firsttriangle;
8074 rsurface.batchnumtriangles = batchnumtriangles;
8076 // this variable holds flags for which properties have been updated that
8077 // may require regenerating vertexmesh array...
8080 // check if any dynamic vertex processing must occur
8081 dynamicvertex = false;
8083 // if there is a chance of animated vertex colors, it's a dynamic batch
8084 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8086 dynamicvertex = true;
8087 batchneed |= BATCHNEED_NOGAPS;
8088 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8091 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8093 switch (deform->deform)
8096 case Q3DEFORM_PROJECTIONSHADOW:
8097 case Q3DEFORM_TEXT0:
8098 case Q3DEFORM_TEXT1:
8099 case Q3DEFORM_TEXT2:
8100 case Q3DEFORM_TEXT3:
8101 case Q3DEFORM_TEXT4:
8102 case Q3DEFORM_TEXT5:
8103 case Q3DEFORM_TEXT6:
8104 case Q3DEFORM_TEXT7:
8107 case Q3DEFORM_AUTOSPRITE:
8108 dynamicvertex = true;
8109 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8110 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8112 case Q3DEFORM_AUTOSPRITE2:
8113 dynamicvertex = true;
8114 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8115 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8117 case Q3DEFORM_NORMAL:
8118 dynamicvertex = true;
8119 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8120 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8123 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8124 break; // if wavefunc is a nop, ignore this transform
8125 dynamicvertex = true;
8126 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8127 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8129 case Q3DEFORM_BULGE:
8130 dynamicvertex = true;
8131 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8132 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8135 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8136 break; // if wavefunc is a nop, ignore this transform
8137 dynamicvertex = true;
8138 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8139 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8143 switch(rsurface.texture->tcgen.tcgen)
8146 case Q3TCGEN_TEXTURE:
8148 case Q3TCGEN_LIGHTMAP:
8149 dynamicvertex = true;
8150 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8151 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8153 case Q3TCGEN_VECTOR:
8154 dynamicvertex = true;
8155 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8156 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8158 case Q3TCGEN_ENVIRONMENT:
8159 dynamicvertex = true;
8160 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8161 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8164 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8166 dynamicvertex = true;
8167 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8168 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8171 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8173 dynamicvertex = true;
8174 batchneed |= BATCHNEED_NOGAPS;
8175 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8178 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8180 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8181 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8182 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8183 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8184 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8185 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8186 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8189 // when the model data has no vertex buffer (dynamic mesh), we need to
8191 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8192 batchneed |= BATCHNEED_NOGAPS;
8194 // if needsupdate, we have to do a dynamic vertex batch for sure
8195 if (needsupdate & batchneed)
8196 dynamicvertex = true;
8198 // see if we need to build vertexmesh from arrays
8199 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8200 dynamicvertex = true;
8202 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8203 // also some drivers strongly dislike firstvertex
8204 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8205 dynamicvertex = true;
8207 rsurface.batchvertex3f = rsurface.modelvertex3f;
8208 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8209 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8210 rsurface.batchsvector3f = rsurface.modelsvector3f;
8211 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8212 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8213 rsurface.batchtvector3f = rsurface.modeltvector3f;
8214 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8215 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8216 rsurface.batchnormal3f = rsurface.modelnormal3f;
8217 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8218 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8219 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8220 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8221 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8222 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8223 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8224 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8225 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8226 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8227 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8228 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8229 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8230 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8231 rsurface.batchelement3i = rsurface.modelelement3i;
8232 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8233 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8234 rsurface.batchelement3s = rsurface.modelelement3s;
8235 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8236 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8238 // if any dynamic vertex processing has to occur in software, we copy the
8239 // entire surface list together before processing to rebase the vertices
8240 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8242 // if any gaps exist and we do not have a static vertex buffer, we have to
8243 // copy the surface list together to avoid wasting upload bandwidth on the
8244 // vertices in the gaps.
8246 // if gaps exist and we have a static vertex buffer, we still have to
8247 // combine the index buffer ranges into one dynamic index buffer.
8249 // in all cases we end up with data that can be drawn in one call.
8253 // static vertex data, just set pointers...
8254 rsurface.batchgeneratedvertex = false;
8255 // if there are gaps, we want to build a combined index buffer,
8256 // otherwise use the original static buffer with an appropriate offset
8259 // build a new triangle elements array for this batch
8260 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8261 rsurface.batchfirsttriangle = 0;
8263 for (i = 0;i < texturenumsurfaces;i++)
8265 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8266 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8267 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8268 numtriangles += surfacenumtriangles;
8270 rsurface.batchelement3i_indexbuffer = NULL;
8271 rsurface.batchelement3i_bufferoffset = 0;
8272 rsurface.batchelement3s = NULL;
8273 rsurface.batchelement3s_indexbuffer = NULL;
8274 rsurface.batchelement3s_bufferoffset = 0;
8275 if (endvertex <= 65536)
8277 // make a 16bit (unsigned short) index array if possible
8278 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8279 for (i = 0;i < numtriangles*3;i++)
8280 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8286 // something needs software processing, do it for real...
8287 // we only directly handle separate array data in this case and then
8288 // generate interleaved data if needed...
8289 rsurface.batchgeneratedvertex = true;
8291 // now copy the vertex data into a combined array and make an index array
8292 // (this is what Quake3 does all the time)
8293 //if (gaps || rsurface.batchfirstvertex)
8295 rsurface.batchvertex3fbuffer = NULL;
8296 rsurface.batchvertexmesh = NULL;
8297 rsurface.batchvertexmeshbuffer = NULL;
8298 rsurface.batchvertex3f = NULL;
8299 rsurface.batchvertex3f_vertexbuffer = NULL;
8300 rsurface.batchvertex3f_bufferoffset = 0;
8301 rsurface.batchsvector3f = NULL;
8302 rsurface.batchsvector3f_vertexbuffer = NULL;
8303 rsurface.batchsvector3f_bufferoffset = 0;
8304 rsurface.batchtvector3f = NULL;
8305 rsurface.batchtvector3f_vertexbuffer = NULL;
8306 rsurface.batchtvector3f_bufferoffset = 0;
8307 rsurface.batchnormal3f = NULL;
8308 rsurface.batchnormal3f_vertexbuffer = NULL;
8309 rsurface.batchnormal3f_bufferoffset = 0;
8310 rsurface.batchlightmapcolor4f = NULL;
8311 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8312 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8313 rsurface.batchtexcoordtexture2f = NULL;
8314 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8315 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8316 rsurface.batchtexcoordlightmap2f = NULL;
8317 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8318 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8319 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8320 rsurface.batchelement3i_indexbuffer = NULL;
8321 rsurface.batchelement3i_bufferoffset = 0;
8322 rsurface.batchelement3s = NULL;
8323 rsurface.batchelement3s_indexbuffer = NULL;
8324 rsurface.batchelement3s_bufferoffset = 0;
8325 // we'll only be setting up certain arrays as needed
8326 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8327 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8328 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8329 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8330 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8331 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8332 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8334 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8335 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8337 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8338 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8339 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8340 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8341 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8342 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8345 for (i = 0;i < texturenumsurfaces;i++)
8347 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8348 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8349 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8350 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8351 // copy only the data requested
8352 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8353 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8354 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8356 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8357 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8358 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8359 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8360 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8362 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8363 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8365 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8366 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8367 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8368 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8369 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8370 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8372 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8373 numvertices += surfacenumvertices;
8374 numtriangles += surfacenumtriangles;
8377 // generate a 16bit index array as well if possible
8378 // (in general, dynamic batches fit)
8379 if (numvertices <= 65536)
8381 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8382 for (i = 0;i < numtriangles*3;i++)
8383 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8386 // since we've copied everything, the batch now starts at 0
8387 rsurface.batchfirstvertex = 0;
8388 rsurface.batchnumvertices = batchnumvertices;
8389 rsurface.batchfirsttriangle = 0;
8390 rsurface.batchnumtriangles = batchnumtriangles;
8393 // q1bsp surfaces rendered in vertex color mode have to have colors
8394 // calculated based on lightstyles
8395 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8397 // generate color arrays for the surfaces in this list
8402 const unsigned char *lm;
8403 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8404 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8405 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8407 for (i = 0;i < texturenumsurfaces;i++)
8409 surface = texturesurfacelist[i];
8410 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8411 surfacenumvertices = surface->num_vertices;
8412 if (surface->lightmapinfo->samples)
8414 for (j = 0;j < surfacenumvertices;j++)
8416 lm = surface->lightmapinfo->samples + offsets[j];
8417 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8418 VectorScale(lm, scale, c);
8419 if (surface->lightmapinfo->styles[1] != 255)
8421 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8423 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8424 VectorMA(c, scale, lm, c);
8425 if (surface->lightmapinfo->styles[2] != 255)
8428 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8429 VectorMA(c, scale, lm, c);
8430 if (surface->lightmapinfo->styles[3] != 255)
8433 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8434 VectorMA(c, scale, lm, c);
8441 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
8447 for (j = 0;j < surfacenumvertices;j++)
8449 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8456 // if vertices are deformed (sprite flares and things in maps, possibly
8457 // water waves, bulges and other deformations), modify the copied vertices
8459 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8461 switch (deform->deform)
8464 case Q3DEFORM_PROJECTIONSHADOW:
8465 case Q3DEFORM_TEXT0:
8466 case Q3DEFORM_TEXT1:
8467 case Q3DEFORM_TEXT2:
8468 case Q3DEFORM_TEXT3:
8469 case Q3DEFORM_TEXT4:
8470 case Q3DEFORM_TEXT5:
8471 case Q3DEFORM_TEXT6:
8472 case Q3DEFORM_TEXT7:
8475 case Q3DEFORM_AUTOSPRITE:
8476 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8477 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8478 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8479 VectorNormalize(newforward);
8480 VectorNormalize(newright);
8481 VectorNormalize(newup);
8482 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8483 // rsurface.batchvertex3f_vertexbuffer = NULL;
8484 // rsurface.batchvertex3f_bufferoffset = 0;
8485 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8486 // rsurface.batchsvector3f_vertexbuffer = NULL;
8487 // rsurface.batchsvector3f_bufferoffset = 0;
8488 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8489 // rsurface.batchtvector3f_vertexbuffer = NULL;
8490 // rsurface.batchtvector3f_bufferoffset = 0;
8491 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8492 // rsurface.batchnormal3f_vertexbuffer = NULL;
8493 // rsurface.batchnormal3f_bufferoffset = 0;
8494 // a single autosprite surface can contain multiple sprites...
8495 for (j = 0;j < batchnumvertices - 3;j += 4)
8497 VectorClear(center);
8498 for (i = 0;i < 4;i++)
8499 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8500 VectorScale(center, 0.25f, center);
8501 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8502 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8503 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8504 for (i = 0;i < 4;i++)
8506 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8507 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8510 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8511 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8512 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8514 case Q3DEFORM_AUTOSPRITE2:
8515 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8516 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8517 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8518 VectorNormalize(newforward);
8519 VectorNormalize(newright);
8520 VectorNormalize(newup);
8521 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8522 // rsurface.batchvertex3f_vertexbuffer = NULL;
8523 // rsurface.batchvertex3f_bufferoffset = 0;
8525 const float *v1, *v2;
8535 memset(shortest, 0, sizeof(shortest));
8536 // a single autosprite surface can contain multiple sprites...
8537 for (j = 0;j < batchnumvertices - 3;j += 4)
8539 VectorClear(center);
8540 for (i = 0;i < 4;i++)
8541 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8542 VectorScale(center, 0.25f, center);
8543 // find the two shortest edges, then use them to define the
8544 // axis vectors for rotating around the central axis
8545 for (i = 0;i < 6;i++)
8547 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8548 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8549 l = VectorDistance2(v1, v2);
8550 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8552 l += (1.0f / 1024.0f);
8553 if (shortest[0].length2 > l || i == 0)
8555 shortest[1] = shortest[0];
8556 shortest[0].length2 = l;
8557 shortest[0].v1 = v1;
8558 shortest[0].v2 = v2;
8560 else if (shortest[1].length2 > l || i == 1)
8562 shortest[1].length2 = l;
8563 shortest[1].v1 = v1;
8564 shortest[1].v2 = v2;
8567 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8568 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8569 // this calculates the right vector from the shortest edge
8570 // and the up vector from the edge midpoints
8571 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8572 VectorNormalize(right);
8573 VectorSubtract(end, start, up);
8574 VectorNormalize(up);
8575 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8576 VectorSubtract(rsurface.localvieworigin, center, forward);
8577 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8578 VectorNegate(forward, forward);
8579 VectorReflect(forward, 0, up, forward);
8580 VectorNormalize(forward);
8581 CrossProduct(up, forward, newright);
8582 VectorNormalize(newright);
8583 // rotate the quad around the up axis vector, this is made
8584 // especially easy by the fact we know the quad is flat,
8585 // so we only have to subtract the center position and
8586 // measure distance along the right vector, and then
8587 // multiply that by the newright vector and add back the
8589 // we also need to subtract the old position to undo the
8590 // displacement from the center, which we do with a
8591 // DotProduct, the subtraction/addition of center is also
8592 // optimized into DotProducts here
8593 l = DotProduct(right, center);
8594 for (i = 0;i < 4;i++)
8596 v1 = rsurface.batchvertex3f + 3*(j+i);
8597 f = DotProduct(right, v1) - l;
8598 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8602 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8604 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8605 // rsurface.batchnormal3f_vertexbuffer = NULL;
8606 // rsurface.batchnormal3f_bufferoffset = 0;
8607 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8609 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8611 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8612 // rsurface.batchsvector3f_vertexbuffer = NULL;
8613 // rsurface.batchsvector3f_bufferoffset = 0;
8614 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8615 // rsurface.batchtvector3f_vertexbuffer = NULL;
8616 // rsurface.batchtvector3f_bufferoffset = 0;
8617 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8620 case Q3DEFORM_NORMAL:
8621 // deform the normals to make reflections wavey
8622 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8623 rsurface.batchnormal3f_vertexbuffer = NULL;
8624 rsurface.batchnormal3f_bufferoffset = 0;
8625 for (j = 0;j < batchnumvertices;j++)
8628 float *normal = rsurface.batchnormal3f + 3*j;
8629 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8630 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8631 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8632 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8633 VectorNormalize(normal);
8635 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8637 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8638 // rsurface.batchsvector3f_vertexbuffer = NULL;
8639 // rsurface.batchsvector3f_bufferoffset = 0;
8640 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8641 // rsurface.batchtvector3f_vertexbuffer = NULL;
8642 // rsurface.batchtvector3f_bufferoffset = 0;
8643 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8647 // deform vertex array to make wavey water and flags and such
8648 waveparms[0] = deform->waveparms[0];
8649 waveparms[1] = deform->waveparms[1];
8650 waveparms[2] = deform->waveparms[2];
8651 waveparms[3] = deform->waveparms[3];
8652 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8653 break; // if wavefunc is a nop, don't make a dynamic vertex array
8654 // this is how a divisor of vertex influence on deformation
8655 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8656 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8657 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8658 // rsurface.batchvertex3f_vertexbuffer = NULL;
8659 // rsurface.batchvertex3f_bufferoffset = 0;
8660 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8661 // rsurface.batchnormal3f_vertexbuffer = NULL;
8662 // rsurface.batchnormal3f_bufferoffset = 0;
8663 for (j = 0;j < batchnumvertices;j++)
8665 // if the wavefunc depends on time, evaluate it per-vertex
8668 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8669 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8671 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8673 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8674 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8675 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8677 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8678 // rsurface.batchsvector3f_vertexbuffer = NULL;
8679 // rsurface.batchsvector3f_bufferoffset = 0;
8680 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8681 // rsurface.batchtvector3f_vertexbuffer = NULL;
8682 // rsurface.batchtvector3f_bufferoffset = 0;
8683 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8686 case Q3DEFORM_BULGE:
8687 // deform vertex array to make the surface have moving bulges
8688 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8689 // rsurface.batchvertex3f_vertexbuffer = NULL;
8690 // rsurface.batchvertex3f_bufferoffset = 0;
8691 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8692 // rsurface.batchnormal3f_vertexbuffer = NULL;
8693 // rsurface.batchnormal3f_bufferoffset = 0;
8694 for (j = 0;j < batchnumvertices;j++)
8696 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8697 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8699 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8700 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8701 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8703 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8704 // rsurface.batchsvector3f_vertexbuffer = NULL;
8705 // rsurface.batchsvector3f_bufferoffset = 0;
8706 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8707 // rsurface.batchtvector3f_vertexbuffer = NULL;
8708 // rsurface.batchtvector3f_bufferoffset = 0;
8709 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8713 // deform vertex array
8714 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8715 break; // if wavefunc is a nop, don't make a dynamic vertex array
8716 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8717 VectorScale(deform->parms, scale, waveparms);
8718 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8719 // rsurface.batchvertex3f_vertexbuffer = NULL;
8720 // rsurface.batchvertex3f_bufferoffset = 0;
8721 for (j = 0;j < batchnumvertices;j++)
8722 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8727 // generate texcoords based on the chosen texcoord source
8728 switch(rsurface.texture->tcgen.tcgen)
8731 case Q3TCGEN_TEXTURE:
8733 case Q3TCGEN_LIGHTMAP:
8734 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8735 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8736 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8737 if (rsurface.batchtexcoordlightmap2f)
8738 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8740 case Q3TCGEN_VECTOR:
8741 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8742 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8743 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8744 for (j = 0;j < batchnumvertices;j++)
8746 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8747 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8750 case Q3TCGEN_ENVIRONMENT:
8751 // make environment reflections using a spheremap
8752 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8753 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8754 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8755 for (j = 0;j < batchnumvertices;j++)
8757 // identical to Q3A's method, but executed in worldspace so
8758 // carried models can be shiny too
8760 float viewer[3], d, reflected[3], worldreflected[3];
8762 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8763 // VectorNormalize(viewer);
8765 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8767 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8768 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8769 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8770 // note: this is proportinal to viewer, so we can normalize later
8772 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8773 VectorNormalize(worldreflected);
8775 // note: this sphere map only uses world x and z!
8776 // so positive and negative y will LOOK THE SAME.
8777 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8778 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8782 // the only tcmod that needs software vertex processing is turbulent, so
8783 // check for it here and apply the changes if needed
8784 // and we only support that as the first one
8785 // (handling a mixture of turbulent and other tcmods would be problematic
8786 // without punting it entirely to a software path)
8787 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8789 amplitude = rsurface.texture->tcmods[0].parms[1];
8790 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8791 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8792 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8793 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8794 for (j = 0;j < batchnumvertices;j++)
8796 rsurface.batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8797 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8801 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8803 // convert the modified arrays to vertex structs
8804 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8805 // rsurface.batchvertexmeshbuffer = NULL;
8806 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8807 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8808 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8809 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8810 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8811 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8812 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8814 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8816 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8817 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8820 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8821 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8822 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8823 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8824 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8825 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8826 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8827 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8828 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8832 void RSurf_DrawBatch(void)
8834 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8835 // through the pipeline, killing it earlier in the pipeline would have
8836 // per-surface overhead rather than per-batch overhead, so it's best to
8837 // reject it here, before it hits glDraw.
8838 if (rsurface.batchnumtriangles == 0)
8841 // batch debugging code
8842 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8848 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8849 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8852 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8854 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8856 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8857 Sys_Error("RSurf_DrawBatch: index %i uses different texture (%s) than surface %i which it belongs to (which uses %s)\n", c, rsurface.texture->name, j, rsurface.modelsurfaces[j].texture->name);
8864 R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
8867 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8869 // pick the closest matching water plane
8870 int planeindex, vertexindex, bestplaneindex = -1;
8874 r_waterstate_waterplane_t *p;
8875 qboolean prepared = false;
8877 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8879 if(p->camera_entity != rsurface.texture->camera_entity)
8884 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8886 if(rsurface.batchnumvertices == 0)
8889 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8891 Matrix4x4_Transform(&rsurface.matrix, v, vert);
8892 d += fabs(PlaneDiff(vert, &p->plane));
8894 if (bestd > d || bestplaneindex < 0)
8897 bestplaneindex = planeindex;
8900 return bestplaneindex;
8901 // NOTE: this MAY return a totally unrelated water plane; we can ignore
8902 // this situation though, as it might be better to render single larger
8903 // batches with useless stuff (backface culled for example) than to
8904 // render multiple smaller batches
8907 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8910 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8911 rsurface.passcolor4f_vertexbuffer = 0;
8912 rsurface.passcolor4f_bufferoffset = 0;
8913 for (i = 0;i < rsurface.batchnumvertices;i++)
8914 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8917 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8924 if (rsurface.passcolor4f)
8926 // generate color arrays
8927 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8928 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8929 rsurface.passcolor4f_vertexbuffer = 0;
8930 rsurface.passcolor4f_bufferoffset = 0;
8931 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
8933 f = RSurf_FogVertex(v);
8942 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8943 rsurface.passcolor4f_vertexbuffer = 0;
8944 rsurface.passcolor4f_bufferoffset = 0;
8945 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8947 f = RSurf_FogVertex(v);
8956 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8963 if (!rsurface.passcolor4f)
8965 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8966 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8967 rsurface.passcolor4f_vertexbuffer = 0;
8968 rsurface.passcolor4f_bufferoffset = 0;
8969 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
8971 f = RSurf_FogVertex(v);
8972 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8973 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8974 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8979 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
8984 if (!rsurface.passcolor4f)
8986 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8987 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8988 rsurface.passcolor4f_vertexbuffer = 0;
8989 rsurface.passcolor4f_bufferoffset = 0;
8990 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
8999 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9004 if (!rsurface.passcolor4f)
9006 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9007 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9008 rsurface.passcolor4f_vertexbuffer = 0;
9009 rsurface.passcolor4f_bufferoffset = 0;
9010 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9012 c2[0] = c[0] + r_refdef.scene.ambient;
9013 c2[1] = c[1] + r_refdef.scene.ambient;
9014 c2[2] = c[2] + r_refdef.scene.ambient;
9019 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9022 rsurface.passcolor4f = NULL;
9023 rsurface.passcolor4f_vertexbuffer = 0;
9024 rsurface.passcolor4f_bufferoffset = 0;
9025 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9026 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9027 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9028 GL_Color(r, g, b, a);
9029 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9033 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9035 // TODO: optimize applyfog && applycolor case
9036 // just apply fog if necessary, and tint the fog color array if necessary
9037 rsurface.passcolor4f = NULL;
9038 rsurface.passcolor4f_vertexbuffer = 0;
9039 rsurface.passcolor4f_bufferoffset = 0;
9040 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9041 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9042 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9043 GL_Color(r, g, b, a);
9047 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9050 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9051 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9052 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9053 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9054 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9055 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9056 GL_Color(r, g, b, a);
9060 static void RSurf_DrawBatch_GL11_ClampColor(void)
9065 if (!rsurface.passcolor4f)
9067 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9069 c2[0] = bound(0.0f, c1[0], 1.0f);
9070 c2[1] = bound(0.0f, c1[1], 1.0f);
9071 c2[2] = bound(0.0f, c1[2], 1.0f);
9072 c2[3] = bound(0.0f, c1[3], 1.0f);
9076 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9086 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9087 rsurface.passcolor4f_vertexbuffer = 0;
9088 rsurface.passcolor4f_bufferoffset = 0;
9089 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
9091 f = -DotProduct(r_refdef.view.forward, n);
9093 f = f * 0.85 + 0.15; // work around so stuff won't get black
9094 f *= r_refdef.lightmapintensity;
9095 Vector4Set(c, f, f, f, 1);
9099 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9101 RSurf_DrawBatch_GL11_ApplyFakeLight();
9102 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9103 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9104 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9105 GL_Color(r, g, b, a);
9109 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9117 vec3_t ambientcolor;
9118 vec3_t diffusecolor;
9122 VectorCopy(rsurface.modellight_lightdir, lightdir);
9123 f = 0.5f * r_refdef.lightmapintensity;
9124 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9125 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9126 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9127 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9128 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9129 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9131 if (VectorLength2(diffusecolor) > 0)
9133 // q3-style directional shading
9134 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9135 rsurface.passcolor4f_vertexbuffer = 0;
9136 rsurface.passcolor4f_bufferoffset = 0;
9137 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
9139 if ((f = DotProduct(n, lightdir)) > 0)
9140 VectorMA(ambientcolor, f, diffusecolor, c);
9142 VectorCopy(ambientcolor, c);
9149 *applycolor = false;
9153 *r = ambientcolor[0];
9154 *g = ambientcolor[1];
9155 *b = ambientcolor[2];
9156 rsurface.passcolor4f = NULL;
9157 rsurface.passcolor4f_vertexbuffer = 0;
9158 rsurface.passcolor4f_bufferoffset = 0;
9162 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9164 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9165 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9166 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9167 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9168 GL_Color(r, g, b, a);
9172 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9178 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9180 f = 1 - RSurf_FogVertex(v);
9188 void RSurf_SetupDepthAndCulling(void)
9190 // submodels are biased to avoid z-fighting with world surfaces that they
9191 // may be exactly overlapping (avoids z-fighting artifacts on certain
9192 // doors and things in Quake maps)
9193 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9194 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9195 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9196 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9199 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9201 // transparent sky would be ridiculous
9202 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9204 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9205 skyrenderlater = true;
9206 RSurf_SetupDepthAndCulling();
9208 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9209 // skymasking on them, and Quake3 never did sky masking (unlike
9210 // software Quake and software Quake2), so disable the sky masking
9211 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9212 // and skymasking also looks very bad when noclipping outside the
9213 // level, so don't use it then either.
9214 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9216 R_Mesh_ResetTextureState();
9217 if (skyrendermasked)
9219 R_SetupShader_DepthOrShadow();
9220 // depth-only (masking)
9221 GL_ColorMask(0,0,0,0);
9222 // just to make sure that braindead drivers don't draw
9223 // anything despite that colormask...
9224 GL_BlendFunc(GL_ZERO, GL_ONE);
9225 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9226 if (rsurface.batchvertex3fbuffer)
9227 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9229 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9233 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9235 GL_BlendFunc(GL_ONE, GL_ZERO);
9236 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9237 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9238 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9241 if (skyrendermasked)
9242 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9244 R_Mesh_ResetTextureState();
9245 GL_Color(1, 1, 1, 1);
9248 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9249 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9250 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9252 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9256 // render screenspace normalmap to texture
9258 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9263 // bind lightmap texture
9265 // water/refraction/reflection/camera surfaces have to be handled specially
9266 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9268 int start, end, startplaneindex;
9269 for (start = 0;start < texturenumsurfaces;start = end)
9271 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9272 if(startplaneindex < 0)
9274 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9275 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9279 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9281 // now that we have a batch using the same planeindex, render it
9282 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9284 // render water or distortion background
9286 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
9288 // blend surface on top
9289 GL_DepthMask(false);
9290 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9293 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9295 // render surface with reflection texture as input
9296 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9297 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
9304 // render surface batch normally
9305 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9306 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9310 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9312 // OpenGL 1.3 path - anything not completely ancient
9313 qboolean applycolor;
9316 const texturelayer_t *layer;
9317 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9318 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9320 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9323 int layertexrgbscale;
9324 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9326 if (layerindex == 0)
9330 GL_AlphaTest(false);
9331 GL_DepthFunc(GL_EQUAL);
9334 GL_DepthMask(layer->depthmask && writedepth);
9335 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9336 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9338 layertexrgbscale = 4;
9339 VectorScale(layer->color, 0.25f, layercolor);
9341 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9343 layertexrgbscale = 2;
9344 VectorScale(layer->color, 0.5f, layercolor);
9348 layertexrgbscale = 1;
9349 VectorScale(layer->color, 1.0f, layercolor);
9351 layercolor[3] = layer->color[3];
9352 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9353 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9354 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9355 switch (layer->type)
9357 case TEXTURELAYERTYPE_LITTEXTURE:
9358 // single-pass lightmapped texture with 2x rgbscale
9359 R_Mesh_TexBind(0, r_texture_white);
9360 R_Mesh_TexMatrix(0, NULL);
9361 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9362 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9363 R_Mesh_TexBind(1, layer->texture);
9364 R_Mesh_TexMatrix(1, &layer->texmatrix);
9365 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9366 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9367 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9368 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9369 else if (FAKELIGHT_ENABLED)
9370 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9371 else if (rsurface.uselightmaptexture)
9372 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9374 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9376 case TEXTURELAYERTYPE_TEXTURE:
9377 // singletexture unlit texture with transparency support
9378 R_Mesh_TexBind(0, layer->texture);
9379 R_Mesh_TexMatrix(0, &layer->texmatrix);
9380 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9381 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9382 R_Mesh_TexBind(1, 0);
9383 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9384 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9386 case TEXTURELAYERTYPE_FOG:
9387 // singletexture fogging
9390 R_Mesh_TexBind(0, layer->texture);
9391 R_Mesh_TexMatrix(0, &layer->texmatrix);
9392 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9393 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9397 R_Mesh_TexBind(0, 0);
9398 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9400 R_Mesh_TexBind(1, 0);
9401 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9402 // generate a color array for the fog pass
9403 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9404 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9408 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9411 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9413 GL_DepthFunc(GL_LEQUAL);
9414 GL_AlphaTest(false);
9418 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9420 // OpenGL 1.1 - crusty old voodoo path
9423 const texturelayer_t *layer;
9424 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9425 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9427 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9429 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9431 if (layerindex == 0)
9435 GL_AlphaTest(false);
9436 GL_DepthFunc(GL_EQUAL);
9439 GL_DepthMask(layer->depthmask && writedepth);
9440 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9441 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9442 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9443 switch (layer->type)
9445 case TEXTURELAYERTYPE_LITTEXTURE:
9446 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9448 // two-pass lit texture with 2x rgbscale
9449 // first the lightmap pass
9450 R_Mesh_TexBind(0, r_texture_white);
9451 R_Mesh_TexMatrix(0, NULL);
9452 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9453 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9454 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9455 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9456 else if (FAKELIGHT_ENABLED)
9457 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9458 else if (rsurface.uselightmaptexture)
9459 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9461 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9462 // then apply the texture to it
9463 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9464 R_Mesh_TexBind(0, layer->texture);
9465 R_Mesh_TexMatrix(0, &layer->texmatrix);
9466 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9467 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9468 RSurf_DrawBatch_GL11_Unlit(layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
9472 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9473 R_Mesh_TexBind(0, layer->texture);
9474 R_Mesh_TexMatrix(0, &layer->texmatrix);
9475 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9476 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9477 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9478 RSurf_DrawBatch_GL11_VertexShade(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
9480 RSurf_DrawBatch_GL11_VertexColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
9483 case TEXTURELAYERTYPE_TEXTURE:
9484 // singletexture unlit texture with transparency support
9485 R_Mesh_TexBind(0, layer->texture);
9486 R_Mesh_TexMatrix(0, &layer->texmatrix);
9487 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9488 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9489 RSurf_DrawBatch_GL11_Unlit(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
9491 case TEXTURELAYERTYPE_FOG:
9492 // singletexture fogging
9495 R_Mesh_TexBind(0, layer->texture);
9496 R_Mesh_TexMatrix(0, &layer->texmatrix);
9497 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9498 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9502 R_Mesh_TexBind(0, 0);
9503 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9505 // generate a color array for the fog pass
9506 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9507 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9511 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9514 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9516 GL_DepthFunc(GL_LEQUAL);
9517 GL_AlphaTest(false);
9521 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9525 r_vertexgeneric_t *batchvertex;
9528 // R_Mesh_ResetTextureState();
9529 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9531 if(rsurface.texture && rsurface.texture->currentskinframe)
9533 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9534 c[3] *= rsurface.texture->currentalpha;
9544 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9546 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9547 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9548 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9551 // brighten it up (as texture value 127 means "unlit")
9552 c[0] *= 2 * r_refdef.view.colorscale;
9553 c[1] *= 2 * r_refdef.view.colorscale;
9554 c[2] *= 2 * r_refdef.view.colorscale;
9556 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9557 c[3] *= r_wateralpha.value;
9559 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9561 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9562 GL_DepthMask(false);
9564 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9566 GL_BlendFunc(GL_ONE, GL_ONE);
9567 GL_DepthMask(false);
9569 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9571 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9572 GL_DepthMask(false);
9574 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9576 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9577 GL_DepthMask(false);
9581 GL_BlendFunc(GL_ONE, GL_ZERO);
9582 GL_DepthMask(writedepth);
9585 if (r_showsurfaces.integer == 3)
9587 rsurface.passcolor4f = NULL;
9589 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9591 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9593 rsurface.passcolor4f = NULL;
9594 rsurface.passcolor4f_vertexbuffer = 0;
9595 rsurface.passcolor4f_bufferoffset = 0;
9597 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9599 qboolean applycolor = true;
9602 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9604 r_refdef.lightmapintensity = 1;
9605 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9606 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9608 else if (FAKELIGHT_ENABLED)
9610 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9612 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9613 RSurf_DrawBatch_GL11_ApplyFakeLight();
9614 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9618 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9620 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9621 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9622 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9625 if(!rsurface.passcolor4f)
9626 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9628 RSurf_DrawBatch_GL11_ApplyAmbient();
9629 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9630 if(r_refdef.fogenabled)
9631 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9632 RSurf_DrawBatch_GL11_ClampColor();
9634 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9635 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9638 else if (!r_refdef.view.showdebug)
9640 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9641 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9642 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9644 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9645 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9647 R_Mesh_PrepareVertices_Generic_Unlock();
9650 else if (r_showsurfaces.integer == 4)
9652 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9653 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9654 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9656 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9657 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9658 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9660 R_Mesh_PrepareVertices_Generic_Unlock();
9663 else if (r_showsurfaces.integer == 2)
9666 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9667 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9668 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9670 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9671 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9672 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9673 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9674 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9675 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9676 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9678 R_Mesh_PrepareVertices_Generic_Unlock();
9679 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9683 int texturesurfaceindex;
9685 const msurface_t *surface;
9686 float surfacecolor4f[4];
9687 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9688 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9690 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9692 surface = texturesurfacelist[texturesurfaceindex];
9693 k = (int)(((size_t)surface) / sizeof(msurface_t));
9694 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9695 for (j = 0;j < surface->num_vertices;j++)
9697 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9698 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9702 R_Mesh_PrepareVertices_Generic_Unlock();
9707 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9710 RSurf_SetupDepthAndCulling();
9711 if (r_showsurfaces.integer)
9713 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9716 switch (vid.renderpath)
9718 case RENDERPATH_GL20:
9719 case RENDERPATH_D3D9:
9720 case RENDERPATH_D3D10:
9721 case RENDERPATH_D3D11:
9722 case RENDERPATH_SOFT:
9723 case RENDERPATH_GLES2:
9724 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9726 case RENDERPATH_GL13:
9727 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9729 case RENDERPATH_GL11:
9730 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9736 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9739 RSurf_SetupDepthAndCulling();
9740 if (r_showsurfaces.integer)
9742 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9745 switch (vid.renderpath)
9747 case RENDERPATH_GL20:
9748 case RENDERPATH_D3D9:
9749 case RENDERPATH_D3D10:
9750 case RENDERPATH_D3D11:
9751 case RENDERPATH_SOFT:
9752 case RENDERPATH_GLES2:
9753 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9755 case RENDERPATH_GL13:
9756 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9758 case RENDERPATH_GL11:
9759 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9765 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9768 int texturenumsurfaces, endsurface;
9770 const msurface_t *surface;
9771 #define MAXBATCH_TRANSPARENTSURFACES 256
9772 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9774 // if the model is static it doesn't matter what value we give for
9775 // wantnormals and wanttangents, so this logic uses only rules applicable
9776 // to a model, knowing that they are meaningless otherwise
9777 if (ent == r_refdef.scene.worldentity)
9778 RSurf_ActiveWorldEntity();
9779 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9780 RSurf_ActiveModelEntity(ent, false, false, false);
9783 switch (vid.renderpath)
9785 case RENDERPATH_GL20:
9786 case RENDERPATH_D3D9:
9787 case RENDERPATH_D3D10:
9788 case RENDERPATH_D3D11:
9789 case RENDERPATH_SOFT:
9790 case RENDERPATH_GLES2:
9791 RSurf_ActiveModelEntity(ent, true, true, false);
9793 case RENDERPATH_GL13:
9794 case RENDERPATH_GL11:
9795 RSurf_ActiveModelEntity(ent, true, false, false);
9800 if (r_transparentdepthmasking.integer)
9802 qboolean setup = false;
9803 for (i = 0;i < numsurfaces;i = j)
9806 surface = rsurface.modelsurfaces + surfacelist[i];
9807 texture = surface->texture;
9808 rsurface.texture = R_GetCurrentTexture(texture);
9809 rsurface.lightmaptexture = NULL;
9810 rsurface.deluxemaptexture = NULL;
9811 rsurface.uselightmaptexture = false;
9812 // scan ahead until we find a different texture
9813 endsurface = min(i + 1024, numsurfaces);
9814 texturenumsurfaces = 0;
9815 texturesurfacelist[texturenumsurfaces++] = surface;
9816 for (;j < endsurface;j++)
9818 surface = rsurface.modelsurfaces + surfacelist[j];
9819 if (texture != surface->texture)
9821 texturesurfacelist[texturenumsurfaces++] = surface;
9823 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9825 // render the range of surfaces as depth
9829 GL_ColorMask(0,0,0,0);
9832 GL_BlendFunc(GL_ONE, GL_ZERO);
9834 // R_Mesh_ResetTextureState();
9835 R_SetupShader_DepthOrShadow();
9837 RSurf_SetupDepthAndCulling();
9838 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9839 if (rsurface.batchvertex3fbuffer)
9840 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9842 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9846 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9849 for (i = 0;i < numsurfaces;i = j)
9852 surface = rsurface.modelsurfaces + surfacelist[i];
9853 texture = surface->texture;
9854 rsurface.texture = R_GetCurrentTexture(texture);
9855 // scan ahead until we find a different texture
9856 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9857 texturenumsurfaces = 0;
9858 texturesurfacelist[texturenumsurfaces++] = surface;
9859 if(FAKELIGHT_ENABLED)
9861 rsurface.lightmaptexture = NULL;
9862 rsurface.deluxemaptexture = NULL;
9863 rsurface.uselightmaptexture = false;
9864 for (;j < endsurface;j++)
9866 surface = rsurface.modelsurfaces + surfacelist[j];
9867 if (texture != surface->texture)
9869 texturesurfacelist[texturenumsurfaces++] = surface;
9874 rsurface.lightmaptexture = surface->lightmaptexture;
9875 rsurface.deluxemaptexture = surface->deluxemaptexture;
9876 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9877 for (;j < endsurface;j++)
9879 surface = rsurface.modelsurfaces + surfacelist[j];
9880 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9882 texturesurfacelist[texturenumsurfaces++] = surface;
9885 // render the range of surfaces
9886 if (ent == r_refdef.scene.worldentity)
9887 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9889 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9891 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9894 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9896 // transparent surfaces get pushed off into the transparent queue
9897 int surfacelistindex;
9898 const msurface_t *surface;
9899 vec3_t tempcenter, center;
9900 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9902 surface = texturesurfacelist[surfacelistindex];
9903 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9904 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9905 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9906 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9907 if (queueentity->transparent_offset) // transparent offset
9909 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9910 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9911 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9913 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9917 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9919 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9921 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9923 RSurf_SetupDepthAndCulling();
9924 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9925 if (rsurface.batchvertex3fbuffer)
9926 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9928 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9932 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9934 const entity_render_t *queueentity = r_refdef.scene.worldentity;
9937 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9940 if (!rsurface.texture->currentnumlayers)
9942 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9943 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9945 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9947 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9948 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9949 else if (!rsurface.texture->currentnumlayers)
9951 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9953 // in the deferred case, transparent surfaces were queued during prepass
9954 if (!r_shadow_usingdeferredprepass)
9955 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9959 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9960 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9965 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9969 R_FrameData_SetMark();
9970 // break the surface list down into batches by texture and use of lightmapping
9971 for (i = 0;i < numsurfaces;i = j)
9974 // texture is the base texture pointer, rsurface.texture is the
9975 // current frame/skin the texture is directing us to use (for example
9976 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9977 // use skin 1 instead)
9978 texture = surfacelist[i]->texture;
9979 rsurface.texture = R_GetCurrentTexture(texture);
9980 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9982 // if this texture is not the kind we want, skip ahead to the next one
9983 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9987 if(FAKELIGHT_ENABLED || depthonly || prepass)
9989 rsurface.lightmaptexture = NULL;
9990 rsurface.deluxemaptexture = NULL;
9991 rsurface.uselightmaptexture = false;
9992 // simply scan ahead until we find a different texture or lightmap state
9993 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9998 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
9999 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10000 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10001 // simply scan ahead until we find a different texture or lightmap state
10002 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10005 // render the range of surfaces
10006 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10008 R_FrameData_ReturnToMark();
10011 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10015 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10018 if (!rsurface.texture->currentnumlayers)
10020 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10021 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10023 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10025 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10026 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10027 else if (!rsurface.texture->currentnumlayers)
10029 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10031 // in the deferred case, transparent surfaces were queued during prepass
10032 if (!r_shadow_usingdeferredprepass)
10033 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10037 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10038 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10043 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10046 texture_t *texture;
10047 R_FrameData_SetMark();
10048 // break the surface list down into batches by texture and use of lightmapping
10049 for (i = 0;i < numsurfaces;i = j)
10052 // texture is the base texture pointer, rsurface.texture is the
10053 // current frame/skin the texture is directing us to use (for example
10054 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10055 // use skin 1 instead)
10056 texture = surfacelist[i]->texture;
10057 rsurface.texture = R_GetCurrentTexture(texture);
10058 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10060 // if this texture is not the kind we want, skip ahead to the next one
10061 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10065 if(FAKELIGHT_ENABLED || depthonly || prepass)
10067 rsurface.lightmaptexture = NULL;
10068 rsurface.deluxemaptexture = NULL;
10069 rsurface.uselightmaptexture = false;
10070 // simply scan ahead until we find a different texture or lightmap state
10071 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10076 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10077 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10078 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10079 // simply scan ahead until we find a different texture or lightmap state
10080 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10083 // render the range of surfaces
10084 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10086 R_FrameData_ReturnToMark();
10089 float locboxvertex3f[6*4*3] =
10091 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10092 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10093 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10094 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10095 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10096 1,0,0, 0,0,0, 0,1,0, 1,1,0
10099 unsigned short locboxelements[6*2*3] =
10104 12,13,14, 12,14,15,
10105 16,17,18, 16,18,19,
10109 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10112 cl_locnode_t *loc = (cl_locnode_t *)ent;
10114 float vertex3f[6*4*3];
10116 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10117 GL_DepthMask(false);
10118 GL_DepthRange(0, 1);
10119 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10120 GL_DepthTest(true);
10121 GL_CullFace(GL_NONE);
10122 R_EntityMatrix(&identitymatrix);
10124 // R_Mesh_ResetTextureState();
10126 i = surfacelist[0];
10127 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10128 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10129 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10130 surfacelist[0] < 0 ? 0.5f : 0.125f);
10132 if (VectorCompare(loc->mins, loc->maxs))
10134 VectorSet(size, 2, 2, 2);
10135 VectorMA(loc->mins, -0.5f, size, mins);
10139 VectorCopy(loc->mins, mins);
10140 VectorSubtract(loc->maxs, loc->mins, size);
10143 for (i = 0;i < 6*4*3;)
10144 for (j = 0;j < 3;j++, i++)
10145 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10147 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10148 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10149 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10152 void R_DrawLocs(void)
10155 cl_locnode_t *loc, *nearestloc;
10157 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10158 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10160 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10161 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10165 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10167 if (decalsystem->decals)
10168 Mem_Free(decalsystem->decals);
10169 memset(decalsystem, 0, sizeof(*decalsystem));
10172 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, int decalsequence)
10175 tridecal_t *decals;
10178 // expand or initialize the system
10179 if (decalsystem->maxdecals <= decalsystem->numdecals)
10181 decalsystem_t old = *decalsystem;
10182 qboolean useshortelements;
10183 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10184 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10185 decalsystem->decals = (tridecal_t *)Mem_Alloc(cls.levelmempool, decalsystem->maxdecals * (sizeof(tridecal_t) + sizeof(float[3][3]) + sizeof(float[3][2]) + sizeof(float[3][4]) + sizeof(int[3]) + (useshortelements ? sizeof(unsigned short[3]) : 0)));
10186 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10187 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10188 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10189 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10190 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10191 if (decalsystem->numdecals)
10192 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10194 Mem_Free(old.decals);
10195 for (i = 0;i < decalsystem->maxdecals*3;i++)
10196 decalsystem->element3i[i] = i;
10197 if (useshortelements)
10198 for (i = 0;i < decalsystem->maxdecals*3;i++)
10199 decalsystem->element3s[i] = i;
10202 // grab a decal and search for another free slot for the next one
10203 decals = decalsystem->decals;
10204 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10205 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10207 decalsystem->freedecal = i;
10208 if (decalsystem->numdecals <= i)
10209 decalsystem->numdecals = i + 1;
10211 // initialize the decal
10213 decal->triangleindex = triangleindex;
10214 decal->surfaceindex = surfaceindex;
10215 decal->decalsequence = decalsequence;
10216 decal->color4f[0][0] = c0[0];
10217 decal->color4f[0][1] = c0[1];
10218 decal->color4f[0][2] = c0[2];
10219 decal->color4f[0][3] = 1;
10220 decal->color4f[1][0] = c1[0];
10221 decal->color4f[1][1] = c1[1];
10222 decal->color4f[1][2] = c1[2];
10223 decal->color4f[1][3] = 1;
10224 decal->color4f[2][0] = c2[0];
10225 decal->color4f[2][1] = c2[1];
10226 decal->color4f[2][2] = c2[2];
10227 decal->color4f[2][3] = 1;
10228 decal->vertex3f[0][0] = v0[0];
10229 decal->vertex3f[0][1] = v0[1];
10230 decal->vertex3f[0][2] = v0[2];
10231 decal->vertex3f[1][0] = v1[0];
10232 decal->vertex3f[1][1] = v1[1];
10233 decal->vertex3f[1][2] = v1[2];
10234 decal->vertex3f[2][0] = v2[0];
10235 decal->vertex3f[2][1] = v2[1];
10236 decal->vertex3f[2][2] = v2[2];
10237 decal->texcoord2f[0][0] = t0[0];
10238 decal->texcoord2f[0][1] = t0[1];
10239 decal->texcoord2f[1][0] = t1[0];
10240 decal->texcoord2f[1][1] = t1[1];
10241 decal->texcoord2f[2][0] = t2[0];
10242 decal->texcoord2f[2][1] = t2[1];
10245 extern cvar_t cl_decals_bias;
10246 extern cvar_t cl_decals_models;
10247 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10248 // baseparms, parms, temps
10249 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
10254 const float *vertex3f;
10255 const float *normal3f;
10257 float points[2][9][3];
10264 e = rsurface.modelelement3i + 3*triangleindex;
10266 vertex3f = rsurface.modelvertex3f;
10267 normal3f = rsurface.modelnormal3f;
10269 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10271 index = 3*e[cornerindex];
10272 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10275 //TriangleNormal(v[0], v[1], v[2], normal);
10276 //if (DotProduct(normal, localnormal) < 0.0f)
10278 // clip by each of the box planes formed from the projection matrix
10279 // if anything survives, we emit the decal
10280 numpoints = PolygonF_Clip(3 , v[0] , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
10283 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
10286 numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
10289 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
10292 numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
10295 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]);
10298 // some part of the triangle survived, so we have to accept it...
10301 // dynamic always uses the original triangle
10303 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10305 index = 3*e[cornerindex];
10306 VectorCopy(vertex3f + index, v[cornerindex]);
10309 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10311 // convert vertex positions to texcoords
10312 Matrix4x4_Transform(projection, v[cornerindex], temp);
10313 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10314 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10315 // calculate distance fade from the projection origin
10316 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10317 f = bound(0.0f, f, 1.0f);
10318 c[cornerindex][0] = r * f;
10319 c[cornerindex][1] = g * f;
10320 c[cornerindex][2] = b * f;
10321 c[cornerindex][3] = 1.0f;
10322 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10325 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence);
10327 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10328 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence);
10330 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
10332 matrix4x4_t projection;
10333 decalsystem_t *decalsystem;
10336 const msurface_t *surface;
10337 const msurface_t *surfaces;
10338 const int *surfacelist;
10339 const texture_t *texture;
10341 int numsurfacelist;
10342 int surfacelistindex;
10345 float localorigin[3];
10346 float localnormal[3];
10347 float localmins[3];
10348 float localmaxs[3];
10351 float planes[6][4];
10354 int bih_triangles_count;
10355 int bih_triangles[256];
10356 int bih_surfaces[256];
10358 decalsystem = &ent->decalsystem;
10359 model = ent->model;
10360 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10362 R_DecalSystem_Reset(&ent->decalsystem);
10366 if (!model->brush.data_leafs && !cl_decals_models.integer)
10368 if (decalsystem->model)
10369 R_DecalSystem_Reset(decalsystem);
10373 if (decalsystem->model != model)
10374 R_DecalSystem_Reset(decalsystem);
10375 decalsystem->model = model;
10377 RSurf_ActiveModelEntity(ent, true, false, false);
10379 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10380 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10381 VectorNormalize(localnormal);
10382 localsize = worldsize*rsurface.inversematrixscale;
10383 localmins[0] = localorigin[0] - localsize;
10384 localmins[1] = localorigin[1] - localsize;
10385 localmins[2] = localorigin[2] - localsize;
10386 localmaxs[0] = localorigin[0] + localsize;
10387 localmaxs[1] = localorigin[1] + localsize;
10388 localmaxs[2] = localorigin[2] + localsize;
10390 //VectorCopy(localnormal, planes[4]);
10391 //VectorVectors(planes[4], planes[2], planes[0]);
10392 AnglesFromVectors(angles, localnormal, NULL, false);
10393 AngleVectors(angles, planes[0], planes[2], planes[4]);
10394 VectorNegate(planes[0], planes[1]);
10395 VectorNegate(planes[2], planes[3]);
10396 VectorNegate(planes[4], planes[5]);
10397 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10398 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10399 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10400 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10401 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10402 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10407 matrix4x4_t forwardprojection;
10408 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10409 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10414 float projectionvector[4][3];
10415 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10416 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10417 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10418 projectionvector[0][0] = planes[0][0] * ilocalsize;
10419 projectionvector[0][1] = planes[1][0] * ilocalsize;
10420 projectionvector[0][2] = planes[2][0] * ilocalsize;
10421 projectionvector[1][0] = planes[0][1] * ilocalsize;
10422 projectionvector[1][1] = planes[1][1] * ilocalsize;
10423 projectionvector[1][2] = planes[2][1] * ilocalsize;
10424 projectionvector[2][0] = planes[0][2] * ilocalsize;
10425 projectionvector[2][1] = planes[1][2] * ilocalsize;
10426 projectionvector[2][2] = planes[2][2] * ilocalsize;
10427 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10428 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10429 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10430 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10434 dynamic = model->surfmesh.isanimated;
10435 numsurfacelist = model->nummodelsurfaces;
10436 surfacelist = model->sortedmodelsurfaces;
10437 surfaces = model->data_surfaces;
10440 bih_triangles_count = -1;
10443 if(model->render_bih.numleafs)
10444 bih = &model->render_bih;
10445 else if(model->collision_bih.numleafs)
10446 bih = &model->collision_bih;
10449 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10450 if(bih_triangles_count == 0)
10452 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10454 if(bih_triangles_count > 0)
10456 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10458 surfaceindex = bih_surfaces[triangleindex];
10459 surface = surfaces + surfaceindex;
10460 texture = surface->texture;
10461 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10463 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10465 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10470 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10472 surfaceindex = surfacelist[surfacelistindex];
10473 surface = surfaces + surfaceindex;
10474 // check cull box first because it rejects more than any other check
10475 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10477 // skip transparent surfaces
10478 texture = surface->texture;
10479 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10481 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10483 numtriangles = surface->num_triangles;
10484 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10485 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10490 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10491 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
10493 int renderentityindex;
10494 float worldmins[3];
10495 float worldmaxs[3];
10496 entity_render_t *ent;
10498 if (!cl_decals_newsystem.integer)
10501 worldmins[0] = worldorigin[0] - worldsize;
10502 worldmins[1] = worldorigin[1] - worldsize;
10503 worldmins[2] = worldorigin[2] - worldsize;
10504 worldmaxs[0] = worldorigin[0] + worldsize;
10505 worldmaxs[1] = worldorigin[1] + worldsize;
10506 worldmaxs[2] = worldorigin[2] + worldsize;
10508 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10510 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10512 ent = r_refdef.scene.entities[renderentityindex];
10513 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10516 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10520 typedef struct r_decalsystem_splatqueue_s
10522 vec3_t worldorigin;
10523 vec3_t worldnormal;
10529 r_decalsystem_splatqueue_t;
10531 int r_decalsystem_numqueued = 0;
10532 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10534 void R_DecalSystem_SplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
10536 r_decalsystem_splatqueue_t *queue;
10538 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10541 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10542 VectorCopy(worldorigin, queue->worldorigin);
10543 VectorCopy(worldnormal, queue->worldnormal);
10544 Vector4Set(queue->color, r, g, b, a);
10545 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10546 queue->worldsize = worldsize;
10547 queue->decalsequence = cl.decalsequence++;
10550 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10553 r_decalsystem_splatqueue_t *queue;
10555 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10556 R_DecalSystem_ApplySplatEntities(queue->worldorigin, queue->worldnormal, queue->color[0], queue->color[1], queue->color[2], queue->color[3], queue->tcrange[0], queue->tcrange[1], queue->tcrange[2], queue->tcrange[3], queue->worldsize, queue->decalsequence);
10557 r_decalsystem_numqueued = 0;
10560 extern cvar_t cl_decals_max;
10561 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10564 decalsystem_t *decalsystem = &ent->decalsystem;
10571 if (!decalsystem->numdecals)
10574 if (r_showsurfaces.integer)
10577 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10579 R_DecalSystem_Reset(decalsystem);
10583 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10584 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10586 if (decalsystem->lastupdatetime)
10587 frametime = (cl.time - decalsystem->lastupdatetime);
10590 decalsystem->lastupdatetime = cl.time;
10591 decal = decalsystem->decals;
10592 numdecals = decalsystem->numdecals;
10594 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10596 if (decal->color4f[0][3])
10598 decal->lived += frametime;
10599 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10601 memset(decal, 0, sizeof(*decal));
10602 if (decalsystem->freedecal > i)
10603 decalsystem->freedecal = i;
10607 decal = decalsystem->decals;
10608 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10611 // collapse the array by shuffling the tail decals into the gaps
10614 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10615 decalsystem->freedecal++;
10616 if (decalsystem->freedecal == numdecals)
10618 decal[decalsystem->freedecal] = decal[--numdecals];
10621 decalsystem->numdecals = numdecals;
10623 if (numdecals <= 0)
10625 // if there are no decals left, reset decalsystem
10626 R_DecalSystem_Reset(decalsystem);
10630 extern skinframe_t *decalskinframe;
10631 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10634 decalsystem_t *decalsystem = &ent->decalsystem;
10643 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10646 numdecals = decalsystem->numdecals;
10650 if (r_showsurfaces.integer)
10653 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10655 R_DecalSystem_Reset(decalsystem);
10659 // if the model is static it doesn't matter what value we give for
10660 // wantnormals and wanttangents, so this logic uses only rules applicable
10661 // to a model, knowing that they are meaningless otherwise
10662 if (ent == r_refdef.scene.worldentity)
10663 RSurf_ActiveWorldEntity();
10665 RSurf_ActiveModelEntity(ent, false, false, false);
10667 decalsystem->lastupdatetime = cl.time;
10668 decal = decalsystem->decals;
10670 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10672 // update vertex positions for animated models
10673 v3f = decalsystem->vertex3f;
10674 c4f = decalsystem->color4f;
10675 t2f = decalsystem->texcoord2f;
10676 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10678 if (!decal->color4f[0][3])
10681 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10684 // update color values for fading decals
10685 if (decal->lived >= cl_decals_time.value)
10686 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10690 c4f[ 0] = decal->color4f[0][0] * alpha;
10691 c4f[ 1] = decal->color4f[0][1] * alpha;
10692 c4f[ 2] = decal->color4f[0][2] * alpha;
10694 c4f[ 4] = decal->color4f[1][0] * alpha;
10695 c4f[ 5] = decal->color4f[1][1] * alpha;
10696 c4f[ 6] = decal->color4f[1][2] * alpha;
10698 c4f[ 8] = decal->color4f[2][0] * alpha;
10699 c4f[ 9] = decal->color4f[2][1] * alpha;
10700 c4f[10] = decal->color4f[2][2] * alpha;
10703 t2f[0] = decal->texcoord2f[0][0];
10704 t2f[1] = decal->texcoord2f[0][1];
10705 t2f[2] = decal->texcoord2f[1][0];
10706 t2f[3] = decal->texcoord2f[1][1];
10707 t2f[4] = decal->texcoord2f[2][0];
10708 t2f[5] = decal->texcoord2f[2][1];
10710 // update vertex positions for animated models
10711 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10713 e = rsurface.modelelement3i + 3*decal->triangleindex;
10714 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10715 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10716 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10720 VectorCopy(decal->vertex3f[0], v3f);
10721 VectorCopy(decal->vertex3f[1], v3f + 3);
10722 VectorCopy(decal->vertex3f[2], v3f + 6);
10725 if (r_refdef.fogenabled)
10727 alpha = RSurf_FogVertex(v3f);
10728 VectorScale(c4f, alpha, c4f);
10729 alpha = RSurf_FogVertex(v3f + 3);
10730 VectorScale(c4f + 4, alpha, c4f + 4);
10731 alpha = RSurf_FogVertex(v3f + 6);
10732 VectorScale(c4f + 8, alpha, c4f + 8);
10743 r_refdef.stats.drawndecals += numtris;
10745 // now render the decals all at once
10746 // (this assumes they all use one particle font texture!)
10747 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
10748 // R_Mesh_ResetTextureState();
10749 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10750 GL_DepthMask(false);
10751 GL_DepthRange(0, 1);
10752 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10753 GL_DepthTest(true);
10754 GL_CullFace(GL_NONE);
10755 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10756 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10757 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10761 static void R_DrawModelDecals(void)
10765 // fade faster when there are too many decals
10766 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10767 for (i = 0;i < r_refdef.scene.numentities;i++)
10768 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10770 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10771 for (i = 0;i < r_refdef.scene.numentities;i++)
10772 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10773 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10775 R_DecalSystem_ApplySplatEntitiesQueue();
10777 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10778 for (i = 0;i < r_refdef.scene.numentities;i++)
10779 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10781 r_refdef.stats.totaldecals += numdecals;
10783 if (r_showsurfaces.integer)
10786 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10788 for (i = 0;i < r_refdef.scene.numentities;i++)
10790 if (!r_refdef.viewcache.entityvisible[i])
10792 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10793 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10797 extern cvar_t mod_collision_bih;
10798 void R_DrawDebugModel(void)
10800 entity_render_t *ent = rsurface.entity;
10801 int i, j, k, l, flagsmask;
10802 const msurface_t *surface;
10803 dp_model_t *model = ent->model;
10806 switch(vid.renderpath)
10808 case RENDERPATH_GL11:
10809 case RENDERPATH_GL13:
10810 case RENDERPATH_GL20:
10812 case RENDERPATH_D3D9:
10813 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10815 case RENDERPATH_D3D10:
10816 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10818 case RENDERPATH_D3D11:
10819 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10821 case RENDERPATH_SOFT:
10822 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10824 case RENDERPATH_GLES2:
10825 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10829 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10831 // R_Mesh_ResetTextureState();
10832 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10833 GL_DepthRange(0, 1);
10834 GL_DepthTest(!r_showdisabledepthtest.integer);
10835 GL_DepthMask(false);
10836 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10838 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10842 qboolean cullbox = ent == r_refdef.scene.worldentity;
10843 const q3mbrush_t *brush;
10844 const bih_t *bih = &model->collision_bih;
10845 const bih_leaf_t *bihleaf;
10846 float vertex3f[3][3];
10847 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10849 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10851 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10853 switch (bihleaf->type)
10856 brush = model->brush.data_brushes + bihleaf->itemindex;
10857 if (brush->colbrushf && brush->colbrushf->numtriangles)
10859 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
10860 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10861 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10864 case BIH_COLLISIONTRIANGLE:
10865 triangleindex = bihleaf->itemindex;
10866 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10867 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10868 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10869 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
10870 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10871 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10873 case BIH_RENDERTRIANGLE:
10874 triangleindex = bihleaf->itemindex;
10875 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10876 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10877 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10878 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
10879 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10880 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10886 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10888 if (r_showtris.integer || (r_shownormals.value != 0))
10890 if (r_showdisabledepthtest.integer)
10892 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10893 GL_DepthMask(false);
10897 GL_BlendFunc(GL_ONE, GL_ZERO);
10898 GL_DepthMask(true);
10900 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10902 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10904 rsurface.texture = R_GetCurrentTexture(surface->texture);
10905 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10907 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10908 if (r_showtris.value > 0)
10910 if (!rsurface.texture->currentlayers->depthmask)
10911 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10912 else if (ent == r_refdef.scene.worldentity)
10913 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10915 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10916 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10917 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10919 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10922 if (r_shownormals.value < 0)
10924 qglBegin(GL_LINES);
10925 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10927 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10928 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10929 qglVertex3f(v[0], v[1], v[2]);
10930 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10931 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10932 qglVertex3f(v[0], v[1], v[2]);
10937 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10939 qglBegin(GL_LINES);
10940 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10942 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10943 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10944 qglVertex3f(v[0], v[1], v[2]);
10945 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10946 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10947 qglVertex3f(v[0], v[1], v[2]);
10951 qglBegin(GL_LINES);
10952 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10954 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10955 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10956 qglVertex3f(v[0], v[1], v[2]);
10957 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10958 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10959 qglVertex3f(v[0], v[1], v[2]);
10963 qglBegin(GL_LINES);
10964 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10966 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10967 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10968 qglVertex3f(v[0], v[1], v[2]);
10969 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10970 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10971 qglVertex3f(v[0], v[1], v[2]);
10978 rsurface.texture = NULL;
10982 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10983 int r_maxsurfacelist = 0;
10984 const msurface_t **r_surfacelist = NULL;
10985 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10987 int i, j, endj, flagsmask;
10988 dp_model_t *model = r_refdef.scene.worldmodel;
10989 msurface_t *surfaces;
10990 unsigned char *update;
10991 int numsurfacelist = 0;
10995 if (r_maxsurfacelist < model->num_surfaces)
10997 r_maxsurfacelist = model->num_surfaces;
10999 Mem_Free((msurface_t**)r_surfacelist);
11000 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11003 RSurf_ActiveWorldEntity();
11005 surfaces = model->data_surfaces;
11006 update = model->brushq1.lightmapupdateflags;
11008 // update light styles on this submodel
11009 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11011 model_brush_lightstyleinfo_t *style;
11012 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11014 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11016 int *list = style->surfacelist;
11017 style->value = r_refdef.scene.lightstylevalue[style->style];
11018 for (j = 0;j < style->numsurfaces;j++)
11019 update[list[j]] = true;
11024 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11028 R_DrawDebugModel();
11029 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11033 rsurface.lightmaptexture = NULL;
11034 rsurface.deluxemaptexture = NULL;
11035 rsurface.uselightmaptexture = false;
11036 rsurface.texture = NULL;
11037 rsurface.rtlight = NULL;
11038 numsurfacelist = 0;
11039 // add visible surfaces to draw list
11040 for (i = 0;i < model->nummodelsurfaces;i++)
11042 j = model->sortedmodelsurfaces[i];
11043 if (r_refdef.viewcache.world_surfacevisible[j])
11044 r_surfacelist[numsurfacelist++] = surfaces + j;
11046 // update lightmaps if needed
11047 if (model->brushq1.firstrender)
11049 model->brushq1.firstrender = false;
11050 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11052 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11056 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11057 if (r_refdef.viewcache.world_surfacevisible[j])
11059 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11061 // don't do anything if there were no surfaces
11062 if (!numsurfacelist)
11064 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11067 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11069 // add to stats if desired
11070 if (r_speeds.integer && !skysurfaces && !depthonly)
11072 r_refdef.stats.world_surfaces += numsurfacelist;
11073 for (j = 0;j < numsurfacelist;j++)
11074 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11077 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11080 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11082 int i, j, endj, flagsmask;
11083 dp_model_t *model = ent->model;
11084 msurface_t *surfaces;
11085 unsigned char *update;
11086 int numsurfacelist = 0;
11090 if (r_maxsurfacelist < model->num_surfaces)
11092 r_maxsurfacelist = model->num_surfaces;
11094 Mem_Free((msurface_t **)r_surfacelist);
11095 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11098 // if the model is static it doesn't matter what value we give for
11099 // wantnormals and wanttangents, so this logic uses only rules applicable
11100 // to a model, knowing that they are meaningless otherwise
11101 if (ent == r_refdef.scene.worldentity)
11102 RSurf_ActiveWorldEntity();
11103 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11104 RSurf_ActiveModelEntity(ent, false, false, false);
11106 RSurf_ActiveModelEntity(ent, true, true, true);
11107 else if (depthonly)
11109 switch (vid.renderpath)
11111 case RENDERPATH_GL20:
11112 case RENDERPATH_D3D9:
11113 case RENDERPATH_D3D10:
11114 case RENDERPATH_D3D11:
11115 case RENDERPATH_SOFT:
11116 case RENDERPATH_GLES2:
11117 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11119 case RENDERPATH_GL13:
11120 case RENDERPATH_GL11:
11121 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11127 switch (vid.renderpath)
11129 case RENDERPATH_GL20:
11130 case RENDERPATH_D3D9:
11131 case RENDERPATH_D3D10:
11132 case RENDERPATH_D3D11:
11133 case RENDERPATH_SOFT:
11134 case RENDERPATH_GLES2:
11135 RSurf_ActiveModelEntity(ent, true, true, false);
11137 case RENDERPATH_GL13:
11138 case RENDERPATH_GL11:
11139 RSurf_ActiveModelEntity(ent, true, false, false);
11144 surfaces = model->data_surfaces;
11145 update = model->brushq1.lightmapupdateflags;
11147 // update light styles
11148 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11150 model_brush_lightstyleinfo_t *style;
11151 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11153 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11155 int *list = style->surfacelist;
11156 style->value = r_refdef.scene.lightstylevalue[style->style];
11157 for (j = 0;j < style->numsurfaces;j++)
11158 update[list[j]] = true;
11163 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11167 R_DrawDebugModel();
11168 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11172 rsurface.lightmaptexture = NULL;
11173 rsurface.deluxemaptexture = NULL;
11174 rsurface.uselightmaptexture = false;
11175 rsurface.texture = NULL;
11176 rsurface.rtlight = NULL;
11177 numsurfacelist = 0;
11178 // add visible surfaces to draw list
11179 for (i = 0;i < model->nummodelsurfaces;i++)
11180 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11181 // don't do anything if there were no surfaces
11182 if (!numsurfacelist)
11184 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11187 // update lightmaps if needed
11191 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11196 R_BuildLightMap(ent, surfaces + j);
11201 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11203 R_BuildLightMap(ent, surfaces + j);
11204 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11206 // add to stats if desired
11207 if (r_speeds.integer && !skysurfaces && !depthonly)
11209 r_refdef.stats.entities_surfaces += numsurfacelist;
11210 for (j = 0;j < numsurfacelist;j++)
11211 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11214 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11217 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11219 static texture_t texture;
11220 static msurface_t surface;
11221 const msurface_t *surfacelist = &surface;
11223 // fake enough texture and surface state to render this geometry
11225 texture.update_lastrenderframe = -1; // regenerate this texture
11226 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11227 texture.currentskinframe = skinframe;
11228 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11229 texture.offsetmapping = OFFSETMAPPING_OFF;
11230 texture.offsetscale = 1;
11231 texture.specularscalemod = 1;
11232 texture.specularpowermod = 1;
11234 surface.texture = &texture;
11235 surface.num_triangles = numtriangles;
11236 surface.num_firsttriangle = firsttriangle;
11237 surface.num_vertices = numvertices;
11238 surface.num_firstvertex = firstvertex;
11241 rsurface.texture = R_GetCurrentTexture(surface.texture);
11242 rsurface.lightmaptexture = NULL;
11243 rsurface.deluxemaptexture = NULL;
11244 rsurface.uselightmaptexture = false;
11245 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11248 void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11250 static msurface_t surface;
11251 const msurface_t *surfacelist = &surface;
11253 // fake enough texture and surface state to render this geometry
11254 surface.texture = texture;
11255 surface.num_triangles = numtriangles;
11256 surface.num_firsttriangle = firsttriangle;
11257 surface.num_vertices = numvertices;
11258 surface.num_firstvertex = firstvertex;
11261 rsurface.texture = R_GetCurrentTexture(surface.texture);
11262 rsurface.lightmaptexture = NULL;
11263 rsurface.deluxemaptexture = NULL;
11264 rsurface.uselightmaptexture = false;
11265 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);