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 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
986 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
987 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
989 // the second pretext is the mode (for example a light source)
990 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
991 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
992 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
993 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
995 // now add all the permutation pretexts
996 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
998 if (permutation & (1<<i))
1000 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1001 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1002 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1003 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1007 // keep line numbers correct
1008 vertstrings_list[vertstrings_count++] = "\n";
1009 geomstrings_list[geomstrings_count++] = "\n";
1010 fragstrings_list[fragstrings_count++] = "\n";
1015 R_CompileShader_AddStaticParms(mode, permutation);
1016 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1017 vertstrings_count += shaderstaticparms_count;
1018 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1019 geomstrings_count += shaderstaticparms_count;
1020 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1021 fragstrings_count += shaderstaticparms_count;
1023 // now append the shader text itself
1024 vertstrings_list[vertstrings_count++] = vertexstring;
1025 geomstrings_list[geomstrings_count++] = geometrystring;
1026 fragstrings_list[fragstrings_count++] = fragmentstring;
1028 // if any sources were NULL, clear the respective list
1030 vertstrings_count = 0;
1031 if (!geometrystring)
1032 geomstrings_count = 0;
1033 if (!fragmentstring)
1034 fragstrings_count = 0;
1036 // compile the shader program
1037 if (vertstrings_count + geomstrings_count + fragstrings_count)
1038 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1042 qglUseProgram(p->program);CHECKGLERROR
1043 // look up all the uniform variable names we care about, so we don't
1044 // have to look them up every time we set them
1046 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1047 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1048 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1049 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1050 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1051 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1052 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1053 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1054 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1055 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1056 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1057 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1058 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1059 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1060 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1061 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1062 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1063 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1064 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1065 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1066 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1067 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1068 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1069 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1070 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1071 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1072 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1073 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1074 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1075 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1076 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1077 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1078 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1079 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1080 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1081 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1082 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1083 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1084 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1085 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1086 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1087 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1088 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1089 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1090 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1091 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1092 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1093 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1094 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1095 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1096 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1097 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1098 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1099 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1100 p->loc_OffsetMapping_Scale = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
1101 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1102 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1103 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1104 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1105 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1106 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1107 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1108 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1109 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1110 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1111 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1112 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1113 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1114 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1115 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1116 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1117 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1118 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1119 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1120 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1121 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1122 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1123 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1124 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1125 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1126 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1127 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1128 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1129 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1130 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1131 // initialize the samplers to refer to the texture units we use
1132 p->tex_Texture_First = -1;
1133 p->tex_Texture_Second = -1;
1134 p->tex_Texture_GammaRamps = -1;
1135 p->tex_Texture_Normal = -1;
1136 p->tex_Texture_Color = -1;
1137 p->tex_Texture_Gloss = -1;
1138 p->tex_Texture_Glow = -1;
1139 p->tex_Texture_SecondaryNormal = -1;
1140 p->tex_Texture_SecondaryColor = -1;
1141 p->tex_Texture_SecondaryGloss = -1;
1142 p->tex_Texture_SecondaryGlow = -1;
1143 p->tex_Texture_Pants = -1;
1144 p->tex_Texture_Shirt = -1;
1145 p->tex_Texture_FogHeightTexture = -1;
1146 p->tex_Texture_FogMask = -1;
1147 p->tex_Texture_Lightmap = -1;
1148 p->tex_Texture_Deluxemap = -1;
1149 p->tex_Texture_Attenuation = -1;
1150 p->tex_Texture_Cube = -1;
1151 p->tex_Texture_Refraction = -1;
1152 p->tex_Texture_Reflection = -1;
1153 p->tex_Texture_ShadowMap2D = -1;
1154 p->tex_Texture_CubeProjection = -1;
1155 p->tex_Texture_ScreenDepth = -1;
1156 p->tex_Texture_ScreenNormalMap = -1;
1157 p->tex_Texture_ScreenDiffuse = -1;
1158 p->tex_Texture_ScreenSpecular = -1;
1159 p->tex_Texture_ReflectMask = -1;
1160 p->tex_Texture_ReflectCube = -1;
1161 p->tex_Texture_BounceGrid = -1;
1163 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1164 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1165 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1166 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1167 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1168 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1169 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1170 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1171 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1172 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1173 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1174 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1175 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1176 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1177 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1178 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1179 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1180 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1181 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1182 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1183 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1184 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1185 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1186 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1187 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1188 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1189 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1190 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1191 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1192 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1194 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1197 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1201 Mem_Free(vertexstring);
1203 Mem_Free(geometrystring);
1205 Mem_Free(fragmentstring);
1208 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1210 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1211 if (r_glsl_permutation != perm)
1213 r_glsl_permutation = perm;
1214 if (!r_glsl_permutation->program)
1216 if (!r_glsl_permutation->compiled)
1217 R_GLSL_CompilePermutation(perm, mode, permutation);
1218 if (!r_glsl_permutation->program)
1220 // remove features until we find a valid permutation
1222 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1224 // reduce i more quickly whenever it would not remove any bits
1225 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1226 if (!(permutation & j))
1229 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1230 if (!r_glsl_permutation->compiled)
1231 R_GLSL_CompilePermutation(perm, mode, permutation);
1232 if (r_glsl_permutation->program)
1235 if (i >= SHADERPERMUTATION_COUNT)
1237 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1238 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1239 qglUseProgram(0);CHECKGLERROR
1240 return; // no bit left to clear, entire mode is broken
1245 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1247 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1248 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1249 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1256 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1257 extern D3DCAPS9 vid_d3d9caps;
1260 struct r_hlsl_permutation_s;
1261 typedef struct r_hlsl_permutation_s
1263 /// hash lookup data
1264 struct r_hlsl_permutation_s *hashnext;
1266 unsigned int permutation;
1268 /// indicates if we have tried compiling this permutation already
1270 /// NULL if compilation failed
1271 IDirect3DVertexShader9 *vertexshader;
1272 IDirect3DPixelShader9 *pixelshader;
1274 r_hlsl_permutation_t;
1276 typedef enum D3DVSREGISTER_e
1278 D3DVSREGISTER_TexMatrix = 0, // float4x4
1279 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1280 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1281 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1282 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1283 D3DVSREGISTER_ModelToLight = 20, // float4x4
1284 D3DVSREGISTER_EyePosition = 24,
1285 D3DVSREGISTER_FogPlane = 25,
1286 D3DVSREGISTER_LightDir = 26,
1287 D3DVSREGISTER_LightPosition = 27,
1291 typedef enum D3DPSREGISTER_e
1293 D3DPSREGISTER_Alpha = 0,
1294 D3DPSREGISTER_BloomBlur_Parameters = 1,
1295 D3DPSREGISTER_ClientTime = 2,
1296 D3DPSREGISTER_Color_Ambient = 3,
1297 D3DPSREGISTER_Color_Diffuse = 4,
1298 D3DPSREGISTER_Color_Specular = 5,
1299 D3DPSREGISTER_Color_Glow = 6,
1300 D3DPSREGISTER_Color_Pants = 7,
1301 D3DPSREGISTER_Color_Shirt = 8,
1302 D3DPSREGISTER_DeferredColor_Ambient = 9,
1303 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1304 D3DPSREGISTER_DeferredColor_Specular = 11,
1305 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1306 D3DPSREGISTER_DeferredMod_Specular = 13,
1307 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1308 D3DPSREGISTER_EyePosition = 15, // unused
1309 D3DPSREGISTER_FogColor = 16,
1310 D3DPSREGISTER_FogHeightFade = 17,
1311 D3DPSREGISTER_FogPlane = 18,
1312 D3DPSREGISTER_FogPlaneViewDist = 19,
1313 D3DPSREGISTER_FogRangeRecip = 20,
1314 D3DPSREGISTER_LightColor = 21,
1315 D3DPSREGISTER_LightDir = 22, // unused
1316 D3DPSREGISTER_LightPosition = 23,
1317 D3DPSREGISTER_OffsetMapping_Scale = 24,
1318 D3DPSREGISTER_PixelSize = 25,
1319 D3DPSREGISTER_ReflectColor = 26,
1320 D3DPSREGISTER_ReflectFactor = 27,
1321 D3DPSREGISTER_ReflectOffset = 28,
1322 D3DPSREGISTER_RefractColor = 29,
1323 D3DPSREGISTER_Saturation = 30,
1324 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1325 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1326 D3DPSREGISTER_ScreenToDepth = 33,
1327 D3DPSREGISTER_ShadowMap_Parameters = 34,
1328 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1329 D3DPSREGISTER_SpecularPower = 36,
1330 D3DPSREGISTER_UserVec1 = 37,
1331 D3DPSREGISTER_UserVec2 = 38,
1332 D3DPSREGISTER_UserVec3 = 39,
1333 D3DPSREGISTER_UserVec4 = 40,
1334 D3DPSREGISTER_ViewTintColor = 41,
1335 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1336 D3DPSREGISTER_BloomColorSubtract = 43,
1337 D3DPSREGISTER_ViewToLight = 44, // float4x4
1338 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1339 D3DPSREGISTER_NormalmapScrollBlend = 52,
1344 /// information about each possible shader permutation
1345 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1346 /// currently selected permutation
1347 r_hlsl_permutation_t *r_hlsl_permutation;
1348 /// storage for permutations linked in the hash table
1349 memexpandablearray_t r_hlsl_permutationarray;
1351 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1353 //unsigned int hashdepth = 0;
1354 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1355 r_hlsl_permutation_t *p;
1356 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1358 if (p->mode == mode && p->permutation == permutation)
1360 //if (hashdepth > 10)
1361 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1366 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1368 p->permutation = permutation;
1369 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1370 r_hlsl_permutationhash[mode][hashindex] = p;
1371 //if (hashdepth > 10)
1372 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1376 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1379 if (!filename || !filename[0])
1381 if (!strcmp(filename, "hlsl/default.hlsl"))
1383 if (!hlslshaderstring)
1385 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1386 if (hlslshaderstring)
1387 Con_DPrintf("Loading shaders from file %s...\n", filename);
1389 hlslshaderstring = (char *)builtinhlslshaderstring;
1391 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1392 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1393 return shaderstring;
1395 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1398 if (printfromdisknotice)
1399 Con_DPrintf("from disk %s... ", filename);
1400 return shaderstring;
1402 return shaderstring;
1406 //#include <d3dx9shader.h>
1407 //#include <d3dx9mesh.h>
1409 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1411 DWORD *vsbin = NULL;
1412 DWORD *psbin = NULL;
1413 fs_offset_t vsbinsize;
1414 fs_offset_t psbinsize;
1415 // IDirect3DVertexShader9 *vs = NULL;
1416 // IDirect3DPixelShader9 *ps = NULL;
1417 ID3DXBuffer *vslog = NULL;
1418 ID3DXBuffer *vsbuffer = NULL;
1419 ID3DXConstantTable *vsconstanttable = NULL;
1420 ID3DXBuffer *pslog = NULL;
1421 ID3DXBuffer *psbuffer = NULL;
1422 ID3DXConstantTable *psconstanttable = NULL;
1425 char temp[MAX_INPUTLINE];
1426 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1427 qboolean debugshader = gl_paranoid.integer != 0;
1428 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1429 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1432 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1433 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1435 if ((!vsbin && vertstring) || (!psbin && fragstring))
1437 const char* dllnames_d3dx9 [] =
1461 dllhandle_t d3dx9_dll = NULL;
1462 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1463 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1464 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1465 dllfunction_t d3dx9_dllfuncs[] =
1467 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1468 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1469 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1472 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1474 DWORD shaderflags = 0;
1476 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1477 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1478 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1479 if (vertstring && vertstring[0])
1483 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1484 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1485 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1486 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1489 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1492 vsbinsize = vsbuffer->GetBufferSize();
1493 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1494 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1495 vsbuffer->Release();
1499 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1500 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1504 if (fragstring && fragstring[0])
1508 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1509 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1510 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1511 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1514 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1517 psbinsize = psbuffer->GetBufferSize();
1518 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1519 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1520 psbuffer->Release();
1524 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1525 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1529 Sys_UnloadLibrary(&d3dx9_dll);
1532 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1536 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1537 if (FAILED(vsresult))
1538 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1539 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1540 if (FAILED(psresult))
1541 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1543 // free the shader data
1544 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1545 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1548 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1551 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1552 int vertstring_length = 0;
1553 int geomstring_length = 0;
1554 int fragstring_length = 0;
1556 char *vertexstring, *geometrystring, *fragmentstring;
1557 char *vertstring, *geomstring, *fragstring;
1558 char permutationname[256];
1559 char cachename[256];
1560 int vertstrings_count = 0;
1561 int geomstrings_count = 0;
1562 int fragstrings_count = 0;
1563 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1564 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1565 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1570 p->vertexshader = NULL;
1571 p->pixelshader = NULL;
1573 permutationname[0] = 0;
1575 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1576 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1577 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1579 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1580 strlcat(cachename, "hlsl/", sizeof(cachename));
1582 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1583 vertstrings_count = 0;
1584 geomstrings_count = 0;
1585 fragstrings_count = 0;
1586 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1587 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1588 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1590 // the first pretext is which type of shader to compile as
1591 // (later these will all be bound together as a program object)
1592 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1593 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1594 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1596 // the second pretext is the mode (for example a light source)
1597 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1598 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1599 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1600 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1601 strlcat(cachename, modeinfo->name, sizeof(cachename));
1603 // now add all the permutation pretexts
1604 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1606 if (permutation & (1<<i))
1608 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1609 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1610 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1611 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1612 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1616 // keep line numbers correct
1617 vertstrings_list[vertstrings_count++] = "\n";
1618 geomstrings_list[geomstrings_count++] = "\n";
1619 fragstrings_list[fragstrings_count++] = "\n";
1624 R_CompileShader_AddStaticParms(mode, permutation);
1625 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1626 vertstrings_count += shaderstaticparms_count;
1627 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1628 geomstrings_count += shaderstaticparms_count;
1629 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1630 fragstrings_count += shaderstaticparms_count;
1632 // replace spaces in the cachename with _ characters
1633 for (i = 0;cachename[i];i++)
1634 if (cachename[i] == ' ')
1637 // now append the shader text itself
1638 vertstrings_list[vertstrings_count++] = vertexstring;
1639 geomstrings_list[geomstrings_count++] = geometrystring;
1640 fragstrings_list[fragstrings_count++] = fragmentstring;
1642 // if any sources were NULL, clear the respective list
1644 vertstrings_count = 0;
1645 if (!geometrystring)
1646 geomstrings_count = 0;
1647 if (!fragmentstring)
1648 fragstrings_count = 0;
1650 vertstring_length = 0;
1651 for (i = 0;i < vertstrings_count;i++)
1652 vertstring_length += strlen(vertstrings_list[i]);
1653 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1654 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1655 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1657 geomstring_length = 0;
1658 for (i = 0;i < geomstrings_count;i++)
1659 geomstring_length += strlen(geomstrings_list[i]);
1660 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1661 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1662 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1664 fragstring_length = 0;
1665 for (i = 0;i < fragstrings_count;i++)
1666 fragstring_length += strlen(fragstrings_list[i]);
1667 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1668 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1669 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1671 // try to load the cached shader, or generate one
1672 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1674 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1675 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1677 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1681 Mem_Free(vertstring);
1683 Mem_Free(geomstring);
1685 Mem_Free(fragstring);
1687 Mem_Free(vertexstring);
1689 Mem_Free(geometrystring);
1691 Mem_Free(fragmentstring);
1694 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1695 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1696 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);}
1697 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);}
1698 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);}
1699 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);}
1701 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1702 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1703 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);}
1704 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);}
1705 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);}
1706 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);}
1708 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1710 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1711 if (r_hlsl_permutation != perm)
1713 r_hlsl_permutation = perm;
1714 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1716 if (!r_hlsl_permutation->compiled)
1717 R_HLSL_CompilePermutation(perm, mode, permutation);
1718 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1720 // remove features until we find a valid permutation
1722 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1724 // reduce i more quickly whenever it would not remove any bits
1725 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1726 if (!(permutation & j))
1729 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1730 if (!r_hlsl_permutation->compiled)
1731 R_HLSL_CompilePermutation(perm, mode, permutation);
1732 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1735 if (i >= SHADERPERMUTATION_COUNT)
1737 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1738 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1739 return; // no bit left to clear, entire mode is broken
1743 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1744 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1746 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1747 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1748 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1752 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1754 DPSOFTRAST_SetShader(mode, permutation);
1755 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1756 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1757 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1760 void R_GLSL_Restart_f(void)
1762 unsigned int i, limit;
1763 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1764 Mem_Free(glslshaderstring);
1765 glslshaderstring = NULL;
1766 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1767 Mem_Free(hlslshaderstring);
1768 hlslshaderstring = NULL;
1769 switch(vid.renderpath)
1771 case RENDERPATH_D3D9:
1774 r_hlsl_permutation_t *p;
1775 r_hlsl_permutation = NULL;
1776 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1777 for (i = 0;i < limit;i++)
1779 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1781 if (p->vertexshader)
1782 IDirect3DVertexShader9_Release(p->vertexshader);
1784 IDirect3DPixelShader9_Release(p->pixelshader);
1785 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1788 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1792 case RENDERPATH_D3D10:
1793 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1795 case RENDERPATH_D3D11:
1796 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1798 case RENDERPATH_GL20:
1799 case RENDERPATH_GLES2:
1801 r_glsl_permutation_t *p;
1802 r_glsl_permutation = NULL;
1803 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1804 for (i = 0;i < limit;i++)
1806 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1808 GL_Backend_FreeProgram(p->program);
1809 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1812 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1815 case RENDERPATH_GL13:
1816 case RENDERPATH_GL11:
1818 case RENDERPATH_SOFT:
1823 void R_GLSL_DumpShader_f(void)
1828 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1831 FS_Print(file, "/* The engine may define the following macros:\n");
1832 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1833 for (i = 0;i < SHADERMODE_COUNT;i++)
1834 FS_Print(file, glslshadermodeinfo[i].pretext);
1835 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1836 FS_Print(file, shaderpermutationinfo[i].pretext);
1837 FS_Print(file, "*/\n");
1838 FS_Print(file, builtinshaderstring);
1840 Con_Printf("glsl/default.glsl written\n");
1843 Con_Printf("failed to write to glsl/default.glsl\n");
1845 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1848 FS_Print(file, "/* The engine may define the following macros:\n");
1849 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1850 for (i = 0;i < SHADERMODE_COUNT;i++)
1851 FS_Print(file, hlslshadermodeinfo[i].pretext);
1852 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1853 FS_Print(file, shaderpermutationinfo[i].pretext);
1854 FS_Print(file, "*/\n");
1855 FS_Print(file, builtinhlslshaderstring);
1857 Con_Printf("hlsl/default.hlsl written\n");
1860 Con_Printf("failed to write to hlsl/default.hlsl\n");
1863 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1866 texturemode = GL_MODULATE;
1867 switch (vid.renderpath)
1869 case RENDERPATH_D3D9:
1871 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))));
1872 R_Mesh_TexBind(GL20TU_FIRST , first );
1873 R_Mesh_TexBind(GL20TU_SECOND, second);
1876 case RENDERPATH_D3D10:
1877 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1879 case RENDERPATH_D3D11:
1880 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1882 case RENDERPATH_GL20:
1883 case RENDERPATH_GLES2:
1884 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))));
1885 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1886 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1888 case RENDERPATH_GL13:
1889 R_Mesh_TexBind(0, first );
1890 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1891 R_Mesh_TexBind(1, second);
1893 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1895 case RENDERPATH_GL11:
1896 R_Mesh_TexBind(0, first );
1898 case RENDERPATH_SOFT:
1899 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))));
1900 R_Mesh_TexBind(GL20TU_FIRST , first );
1901 R_Mesh_TexBind(GL20TU_SECOND, second);
1906 void R_SetupShader_DepthOrShadow(void)
1908 switch (vid.renderpath)
1910 case RENDERPATH_D3D9:
1912 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1915 case RENDERPATH_D3D10:
1916 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1918 case RENDERPATH_D3D11:
1919 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1921 case RENDERPATH_GL20:
1922 case RENDERPATH_GLES2:
1923 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1925 case RENDERPATH_GL13:
1926 R_Mesh_TexBind(0, 0);
1927 R_Mesh_TexBind(1, 0);
1929 case RENDERPATH_GL11:
1930 R_Mesh_TexBind(0, 0);
1932 case RENDERPATH_SOFT:
1933 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1938 void R_SetupShader_ShowDepth(void)
1940 switch (vid.renderpath)
1942 case RENDERPATH_D3D9:
1944 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1947 case RENDERPATH_D3D10:
1948 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1950 case RENDERPATH_D3D11:
1951 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1953 case RENDERPATH_GL20:
1954 case RENDERPATH_GLES2:
1955 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1957 case RENDERPATH_GL13:
1959 case RENDERPATH_GL11:
1961 case RENDERPATH_SOFT:
1962 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1967 extern qboolean r_shadow_usingdeferredprepass;
1968 extern cvar_t r_shadow_deferred_8bitrange;
1969 extern rtexture_t *r_shadow_attenuationgradienttexture;
1970 extern rtexture_t *r_shadow_attenuation2dtexture;
1971 extern rtexture_t *r_shadow_attenuation3dtexture;
1972 extern qboolean r_shadow_usingshadowmap2d;
1973 extern qboolean r_shadow_usingshadowmaportho;
1974 extern float r_shadow_shadowmap_texturescale[2];
1975 extern float r_shadow_shadowmap_parameters[4];
1976 extern qboolean r_shadow_shadowmapvsdct;
1977 extern qboolean r_shadow_shadowmapsampler;
1978 extern int r_shadow_shadowmappcf;
1979 extern rtexture_t *r_shadow_shadowmap2dtexture;
1980 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1981 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1982 extern matrix4x4_t r_shadow_shadowmapmatrix;
1983 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1984 extern int r_shadow_prepass_width;
1985 extern int r_shadow_prepass_height;
1986 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1987 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1988 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
1989 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
1990 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
1992 #define BLENDFUNC_ALLOWS_COLORMOD 1
1993 #define BLENDFUNC_ALLOWS_FOG 2
1994 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
1995 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
1996 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
1997 static int R_BlendFuncFlags(int src, int dst)
2001 // a blendfunc allows colormod if:
2002 // a) it can never keep the destination pixel invariant, or
2003 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2004 // this is to prevent unintended side effects from colormod
2006 // a blendfunc allows fog if:
2007 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2008 // this is to prevent unintended side effects from fog
2010 // these checks are the output of fogeval.pl
2012 r |= BLENDFUNC_ALLOWS_COLORMOD;
2013 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2014 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2015 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2016 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2017 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2018 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2019 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2020 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2021 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2022 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2023 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2024 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2025 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2026 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2027 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2028 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2029 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2030 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2031 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2032 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2033 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2038 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)
2040 // select a permutation of the lighting shader appropriate to this
2041 // combination of texture, entity, light source, and fogging, only use the
2042 // minimum features necessary to avoid wasting rendering time in the
2043 // fragment shader on features that are not being used
2044 unsigned int permutation = 0;
2045 unsigned int mode = 0;
2047 static float dummy_colormod[3] = {1, 1, 1};
2048 float *colormod = rsurface.colormod;
2050 matrix4x4_t tempmatrix;
2051 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2052 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2053 permutation |= SHADERPERMUTATION_ALPHAKILL;
2054 if (rsurfacepass == RSURFPASS_BACKGROUND)
2056 // distorted background
2057 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2059 mode = SHADERMODE_WATER;
2060 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2061 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2062 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2064 // this is the right thing to do for wateralpha
2065 GL_BlendFunc(GL_ONE, GL_ZERO);
2066 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2070 // this is the right thing to do for entity alpha
2071 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2072 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2075 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2077 mode = SHADERMODE_REFRACTION;
2078 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2079 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2083 mode = SHADERMODE_GENERIC;
2084 permutation |= SHADERPERMUTATION_DIFFUSE;
2085 GL_BlendFunc(GL_ONE, GL_ZERO);
2086 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2089 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2091 if (r_glsl_offsetmapping.integer)
2093 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2094 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2095 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2096 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2097 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2099 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2100 if (r_glsl_offsetmapping_reliefmapping.integer)
2101 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2104 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2105 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2106 // normalmap (deferred prepass), may use alpha test on diffuse
2107 mode = SHADERMODE_DEFERREDGEOMETRY;
2108 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2109 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2110 GL_BlendFunc(GL_ONE, GL_ZERO);
2111 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2113 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2115 if (r_glsl_offsetmapping.integer)
2117 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2118 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2119 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2120 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2121 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2123 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2124 if (r_glsl_offsetmapping_reliefmapping.integer)
2125 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2128 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2129 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2131 mode = SHADERMODE_LIGHTSOURCE;
2132 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2133 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2134 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2135 permutation |= SHADERPERMUTATION_CUBEFILTER;
2136 if (diffusescale > 0)
2137 permutation |= SHADERPERMUTATION_DIFFUSE;
2138 if (specularscale > 0)
2139 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2140 if (r_refdef.fogenabled)
2141 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2142 if (rsurface.texture->colormapping)
2143 permutation |= SHADERPERMUTATION_COLORMAPPING;
2144 if (r_shadow_usingshadowmap2d)
2146 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2147 if(r_shadow_shadowmapvsdct)
2148 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2150 if (r_shadow_shadowmapsampler)
2151 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2152 if (r_shadow_shadowmappcf > 1)
2153 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2154 else if (r_shadow_shadowmappcf)
2155 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2157 if (rsurface.texture->reflectmasktexture)
2158 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2159 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2160 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2162 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2164 if (r_glsl_offsetmapping.integer)
2166 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2167 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2168 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2169 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2170 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2172 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2173 if (r_glsl_offsetmapping_reliefmapping.integer)
2174 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2177 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2178 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2179 // unshaded geometry (fullbright or ambient model lighting)
2180 mode = SHADERMODE_FLATCOLOR;
2181 ambientscale = diffusescale = specularscale = 0;
2182 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2183 permutation |= SHADERPERMUTATION_GLOW;
2184 if (r_refdef.fogenabled)
2185 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2186 if (rsurface.texture->colormapping)
2187 permutation |= SHADERPERMUTATION_COLORMAPPING;
2188 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2190 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2191 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2193 if (r_shadow_shadowmapsampler)
2194 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2195 if (r_shadow_shadowmappcf > 1)
2196 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2197 else if (r_shadow_shadowmappcf)
2198 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2200 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2201 permutation |= SHADERPERMUTATION_REFLECTION;
2202 if (rsurface.texture->reflectmasktexture)
2203 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2204 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2205 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2207 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2209 if (r_glsl_offsetmapping.integer)
2211 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2212 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2213 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2214 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2215 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2217 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2218 if (r_glsl_offsetmapping_reliefmapping.integer)
2219 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2222 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2223 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2224 // directional model lighting
2225 mode = SHADERMODE_LIGHTDIRECTION;
2226 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2227 permutation |= SHADERPERMUTATION_GLOW;
2228 permutation |= SHADERPERMUTATION_DIFFUSE;
2229 if (specularscale > 0)
2230 permutation |= SHADERPERMUTATION_SPECULAR;
2231 if (r_refdef.fogenabled)
2232 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2233 if (rsurface.texture->colormapping)
2234 permutation |= SHADERPERMUTATION_COLORMAPPING;
2235 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2237 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2238 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2240 if (r_shadow_shadowmapsampler)
2241 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2242 if (r_shadow_shadowmappcf > 1)
2243 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2244 else if (r_shadow_shadowmappcf)
2245 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2247 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2248 permutation |= SHADERPERMUTATION_REFLECTION;
2249 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2250 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2251 if (rsurface.texture->reflectmasktexture)
2252 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2253 if (r_shadow_bouncegridtexture)
2254 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2255 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2256 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2258 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2260 if (r_glsl_offsetmapping.integer)
2262 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2263 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2264 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2265 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2266 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2268 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2269 if (r_glsl_offsetmapping_reliefmapping.integer)
2270 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2273 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2274 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2275 // ambient model lighting
2276 mode = SHADERMODE_LIGHTDIRECTION;
2277 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2278 permutation |= SHADERPERMUTATION_GLOW;
2279 if (r_refdef.fogenabled)
2280 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2281 if (rsurface.texture->colormapping)
2282 permutation |= SHADERPERMUTATION_COLORMAPPING;
2283 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2285 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2286 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2288 if (r_shadow_shadowmapsampler)
2289 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2290 if (r_shadow_shadowmappcf > 1)
2291 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2292 else if (r_shadow_shadowmappcf)
2293 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2295 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2296 permutation |= SHADERPERMUTATION_REFLECTION;
2297 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2298 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2299 if (rsurface.texture->reflectmasktexture)
2300 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2301 if (r_shadow_bouncegridtexture)
2302 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2303 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2304 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2308 if (r_glsl_offsetmapping.integer)
2310 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2311 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2312 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2313 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2314 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2316 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2317 if (r_glsl_offsetmapping_reliefmapping.integer)
2318 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2321 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2322 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2324 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2325 permutation |= SHADERPERMUTATION_GLOW;
2326 if (r_refdef.fogenabled)
2327 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2328 if (rsurface.texture->colormapping)
2329 permutation |= SHADERPERMUTATION_COLORMAPPING;
2330 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2332 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2333 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2335 if (r_shadow_shadowmapsampler)
2336 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2337 if (r_shadow_shadowmappcf > 1)
2338 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2339 else if (r_shadow_shadowmappcf)
2340 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2342 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2343 permutation |= SHADERPERMUTATION_REFLECTION;
2344 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2345 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2346 if (rsurface.texture->reflectmasktexture)
2347 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2348 if (FAKELIGHT_ENABLED)
2350 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2351 mode = SHADERMODE_FAKELIGHT;
2352 permutation |= SHADERPERMUTATION_DIFFUSE;
2353 if (specularscale > 0)
2354 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2356 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2358 // deluxemapping (light direction texture)
2359 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2360 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2362 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2363 permutation |= SHADERPERMUTATION_DIFFUSE;
2364 if (specularscale > 0)
2365 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2367 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2369 // fake deluxemapping (uniform light direction in tangentspace)
2370 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2371 permutation |= SHADERPERMUTATION_DIFFUSE;
2372 if (specularscale > 0)
2373 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2375 else if (rsurface.uselightmaptexture)
2377 // ordinary lightmapping (q1bsp, q3bsp)
2378 mode = SHADERMODE_LIGHTMAP;
2382 // ordinary vertex coloring (q3bsp)
2383 mode = SHADERMODE_VERTEXCOLOR;
2385 if (r_shadow_bouncegridtexture)
2386 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2387 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2388 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2390 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2391 colormod = dummy_colormod;
2392 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2393 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2394 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2395 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2396 switch(vid.renderpath)
2398 case RENDERPATH_D3D9:
2400 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);
2401 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2402 R_SetupShader_SetPermutationHLSL(mode, permutation);
2403 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2404 if (mode == SHADERMODE_LIGHTSOURCE)
2406 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2407 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2411 if (mode == SHADERMODE_LIGHTDIRECTION)
2413 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2416 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2417 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2418 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2419 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2420 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2422 if (mode == SHADERMODE_LIGHTSOURCE)
2424 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2425 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2426 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2427 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2428 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2430 // additive passes are only darkened by fog, not tinted
2431 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2432 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2436 if (mode == SHADERMODE_FLATCOLOR)
2438 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2440 else if (mode == SHADERMODE_LIGHTDIRECTION)
2442 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]);
2443 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2444 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);
2445 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);
2446 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2447 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2448 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2452 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2453 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2454 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2455 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2456 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2458 // additive passes are only darkened by fog, not tinted
2459 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2460 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2462 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2463 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);
2464 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2465 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2466 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2467 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2468 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2469 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2470 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2471 if (mode == SHADERMODE_WATER)
2472 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2474 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2475 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2476 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2477 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));
2478 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2479 if (rsurface.texture->pantstexture)
2480 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2482 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2483 if (rsurface.texture->shirttexture)
2484 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2486 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2487 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2488 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2489 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2490 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2491 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2492 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2493 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2495 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2496 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2497 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2498 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2499 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2500 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2501 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2502 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2503 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2504 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2505 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2506 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2507 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2508 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2509 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2510 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2511 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2512 if (rsurfacepass == RSURFPASS_BACKGROUND)
2514 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2515 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2516 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2520 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2522 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2523 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2524 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2525 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2526 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2528 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2529 if (rsurface.rtlight)
2531 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2532 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2537 case RENDERPATH_D3D10:
2538 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2540 case RENDERPATH_D3D11:
2541 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2543 case RENDERPATH_GL20:
2544 case RENDERPATH_GLES2:
2545 if (!vid.useinterleavedarrays)
2547 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);
2548 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2549 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2550 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2551 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2552 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2553 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2554 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2558 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);
2559 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2561 R_SetupShader_SetPermutationGLSL(mode, permutation);
2562 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2563 if (mode == SHADERMODE_LIGHTSOURCE)
2565 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2566 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2567 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2568 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2569 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2570 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);
2572 // additive passes are only darkened by fog, not tinted
2573 if (r_glsl_permutation->loc_FogColor >= 0)
2574 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2575 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2579 if (mode == SHADERMODE_FLATCOLOR)
2581 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2583 else if (mode == SHADERMODE_LIGHTDIRECTION)
2585 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]);
2586 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]);
2587 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);
2588 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);
2589 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);
2590 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]);
2591 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]);
2595 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]);
2596 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]);
2597 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2598 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2599 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2601 // additive passes are only darkened by fog, not tinted
2602 if (r_glsl_permutation->loc_FogColor >= 0)
2604 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2605 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2607 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2609 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);
2610 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]);
2611 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]);
2612 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]);
2613 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]);
2614 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2615 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2616 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2617 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]);
2619 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2620 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2621 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2622 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]);
2623 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]);
2625 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2626 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));
2627 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2628 if (r_glsl_permutation->loc_Color_Pants >= 0)
2630 if (rsurface.texture->pantstexture)
2631 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2633 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2635 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2637 if (rsurface.texture->shirttexture)
2638 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2640 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2642 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]);
2643 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2644 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2645 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2646 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2647 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]);
2648 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2649 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);}
2650 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2652 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2653 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2654 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2655 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2656 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2657 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2658 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2659 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2660 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2661 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2662 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2663 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2664 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2665 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2666 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);
2667 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2668 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2669 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2670 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2671 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2672 if (rsurfacepass == RSURFPASS_BACKGROUND)
2674 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);
2675 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);
2676 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);
2680 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);
2682 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2683 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2684 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2685 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2686 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2688 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2689 if (rsurface.rtlight)
2691 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2692 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2695 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2698 case RENDERPATH_GL13:
2699 case RENDERPATH_GL11:
2701 case RENDERPATH_SOFT:
2702 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);
2703 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2704 R_SetupShader_SetPermutationSoft(mode, permutation);
2705 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2706 if (mode == SHADERMODE_LIGHTSOURCE)
2708 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2709 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2710 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2711 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2712 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2713 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2715 // additive passes are only darkened by fog, not tinted
2716 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2717 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2721 if (mode == SHADERMODE_FLATCOLOR)
2723 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2725 else if (mode == SHADERMODE_LIGHTDIRECTION)
2727 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]);
2728 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2729 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);
2730 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);
2731 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2732 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]);
2733 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2737 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2738 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2739 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2740 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2741 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2743 // additive passes are only darkened by fog, not tinted
2744 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2745 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2747 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2748 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);
2749 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2750 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2751 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]);
2752 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]);
2753 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2754 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2755 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2756 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2758 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2759 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2760 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2761 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2762 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]);
2764 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2765 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));
2766 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2767 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2769 if (rsurface.texture->pantstexture)
2770 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2772 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2774 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2776 if (rsurface.texture->shirttexture)
2777 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2779 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2781 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2782 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2783 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2784 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2785 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2786 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2787 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2789 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2790 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2791 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2792 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2793 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2794 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2795 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2796 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2797 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2798 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2799 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2800 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2801 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2802 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2803 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2804 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2805 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2806 if (rsurfacepass == RSURFPASS_BACKGROUND)
2808 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2809 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2810 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2814 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2816 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2817 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2818 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2819 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2820 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2822 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2823 if (rsurface.rtlight)
2825 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2826 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2833 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2835 // select a permutation of the lighting shader appropriate to this
2836 // combination of texture, entity, light source, and fogging, only use the
2837 // minimum features necessary to avoid wasting rendering time in the
2838 // fragment shader on features that are not being used
2839 unsigned int permutation = 0;
2840 unsigned int mode = 0;
2841 const float *lightcolorbase = rtlight->currentcolor;
2842 float ambientscale = rtlight->ambientscale;
2843 float diffusescale = rtlight->diffusescale;
2844 float specularscale = rtlight->specularscale;
2845 // this is the location of the light in view space
2846 vec3_t viewlightorigin;
2847 // this transforms from view space (camera) to light space (cubemap)
2848 matrix4x4_t viewtolight;
2849 matrix4x4_t lighttoview;
2850 float viewtolight16f[16];
2851 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2853 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2854 if (rtlight->currentcubemap != r_texture_whitecube)
2855 permutation |= SHADERPERMUTATION_CUBEFILTER;
2856 if (diffusescale > 0)
2857 permutation |= SHADERPERMUTATION_DIFFUSE;
2858 if (specularscale > 0)
2859 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2860 if (r_shadow_usingshadowmap2d)
2862 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2863 if (r_shadow_shadowmapvsdct)
2864 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2866 if (r_shadow_shadowmapsampler)
2867 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2868 if (r_shadow_shadowmappcf > 1)
2869 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2870 else if (r_shadow_shadowmappcf)
2871 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2873 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2874 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2875 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2876 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2877 switch(vid.renderpath)
2879 case RENDERPATH_D3D9:
2881 R_SetupShader_SetPermutationHLSL(mode, permutation);
2882 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2883 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2884 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2885 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2886 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2887 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2888 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2889 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2890 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2891 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2893 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2894 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2895 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2896 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2897 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2898 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2901 case RENDERPATH_D3D10:
2902 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2904 case RENDERPATH_D3D11:
2905 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2907 case RENDERPATH_GL20:
2908 case RENDERPATH_GLES2:
2909 R_SetupShader_SetPermutationGLSL(mode, permutation);
2910 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2911 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2912 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);
2913 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);
2914 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);
2915 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]);
2916 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]);
2917 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));
2918 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]);
2919 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2921 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2922 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2923 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2924 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2925 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2926 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2928 case RENDERPATH_GL13:
2929 case RENDERPATH_GL11:
2931 case RENDERPATH_SOFT:
2932 R_SetupShader_SetPermutationGLSL(mode, permutation);
2933 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2934 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2935 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2936 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2937 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2938 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2939 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]);
2940 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));
2941 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2942 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2944 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2945 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2946 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2947 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2948 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2949 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2954 #define SKINFRAME_HASH 1024
2958 int loadsequence; // incremented each level change
2959 memexpandablearray_t array;
2960 skinframe_t *hash[SKINFRAME_HASH];
2963 r_skinframe_t r_skinframe;
2965 void R_SkinFrame_PrepareForPurge(void)
2967 r_skinframe.loadsequence++;
2968 // wrap it without hitting zero
2969 if (r_skinframe.loadsequence >= 200)
2970 r_skinframe.loadsequence = 1;
2973 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2977 // mark the skinframe as used for the purging code
2978 skinframe->loadsequence = r_skinframe.loadsequence;
2981 void R_SkinFrame_Purge(void)
2985 for (i = 0;i < SKINFRAME_HASH;i++)
2987 for (s = r_skinframe.hash[i];s;s = s->next)
2989 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2991 if (s->merged == s->base)
2993 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2994 R_PurgeTexture(s->stain );s->stain = NULL;
2995 R_PurgeTexture(s->merged);s->merged = NULL;
2996 R_PurgeTexture(s->base );s->base = NULL;
2997 R_PurgeTexture(s->pants );s->pants = NULL;
2998 R_PurgeTexture(s->shirt );s->shirt = NULL;
2999 R_PurgeTexture(s->nmap );s->nmap = NULL;
3000 R_PurgeTexture(s->gloss );s->gloss = NULL;
3001 R_PurgeTexture(s->glow );s->glow = NULL;
3002 R_PurgeTexture(s->fog );s->fog = NULL;
3003 R_PurgeTexture(s->reflect);s->reflect = NULL;
3004 s->loadsequence = 0;
3010 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3012 char basename[MAX_QPATH];
3014 Image_StripImageExtension(name, basename, sizeof(basename));
3016 if( last == NULL ) {
3018 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3019 item = r_skinframe.hash[hashindex];
3024 // linearly search through the hash bucket
3025 for( ; item ; item = item->next ) {
3026 if( !strcmp( item->basename, basename ) ) {
3033 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3037 char basename[MAX_QPATH];
3039 Image_StripImageExtension(name, basename, sizeof(basename));
3041 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3042 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3043 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3047 rtexture_t *dyntexture;
3048 // check whether its a dynamic texture
3049 dyntexture = CL_GetDynTexture( basename );
3050 if (!add && !dyntexture)
3052 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3053 memset(item, 0, sizeof(*item));
3054 strlcpy(item->basename, basename, sizeof(item->basename));
3055 item->base = dyntexture; // either NULL or dyntexture handle
3056 item->textureflags = textureflags;
3057 item->comparewidth = comparewidth;
3058 item->compareheight = compareheight;
3059 item->comparecrc = comparecrc;
3060 item->next = r_skinframe.hash[hashindex];
3061 r_skinframe.hash[hashindex] = item;
3063 else if( item->base == NULL )
3065 rtexture_t *dyntexture;
3066 // check whether its a dynamic texture
3067 // 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]
3068 dyntexture = CL_GetDynTexture( basename );
3069 item->base = dyntexture; // either NULL or dyntexture handle
3072 R_SkinFrame_MarkUsed(item);
3076 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3078 unsigned long long avgcolor[5], wsum; \
3086 for(pix = 0; pix < cnt; ++pix) \
3089 for(comp = 0; comp < 3; ++comp) \
3091 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3094 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3096 for(comp = 0; comp < 3; ++comp) \
3097 avgcolor[comp] += getpixel * w; \
3100 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3101 avgcolor[4] += getpixel; \
3103 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3105 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3106 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3107 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3108 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3111 extern cvar_t gl_picmip;
3112 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3115 unsigned char *pixels;
3116 unsigned char *bumppixels;
3117 unsigned char *basepixels = NULL;
3118 int basepixels_width = 0;
3119 int basepixels_height = 0;
3120 skinframe_t *skinframe;
3121 rtexture_t *ddsbase = NULL;
3122 qboolean ddshasalpha = false;
3123 float ddsavgcolor[4];
3124 char basename[MAX_QPATH];
3125 int miplevel = R_PicmipForFlags(textureflags);
3126 int savemiplevel = miplevel;
3129 if (cls.state == ca_dedicated)
3132 // return an existing skinframe if already loaded
3133 // if loading of the first image fails, don't make a new skinframe as it
3134 // would cause all future lookups of this to be missing
3135 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3136 if (skinframe && skinframe->base)
3139 Image_StripImageExtension(name, basename, sizeof(basename));
3141 // check for DDS texture file first
3142 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3144 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3145 if (basepixels == NULL)
3149 // FIXME handle miplevel
3151 if (developer_loading.integer)
3152 Con_Printf("loading skin \"%s\"\n", name);
3154 // we've got some pixels to store, so really allocate this new texture now
3156 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3157 skinframe->stain = NULL;
3158 skinframe->merged = NULL;
3159 skinframe->base = NULL;
3160 skinframe->pants = NULL;
3161 skinframe->shirt = NULL;
3162 skinframe->nmap = NULL;
3163 skinframe->gloss = NULL;
3164 skinframe->glow = NULL;
3165 skinframe->fog = NULL;
3166 skinframe->reflect = NULL;
3167 skinframe->hasalpha = false;
3171 skinframe->base = ddsbase;
3172 skinframe->hasalpha = ddshasalpha;
3173 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3174 if (r_loadfog && skinframe->hasalpha)
3175 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3176 //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]);
3180 basepixels_width = image_width;
3181 basepixels_height = image_height;
3182 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);
3183 if (textureflags & TEXF_ALPHA)
3185 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3187 if (basepixels[j] < 255)
3189 skinframe->hasalpha = true;
3193 if (r_loadfog && skinframe->hasalpha)
3195 // has transparent pixels
3196 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3197 for (j = 0;j < image_width * image_height * 4;j += 4)
3202 pixels[j+3] = basepixels[j+3];
3204 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);
3208 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3209 //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]);
3210 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3211 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3212 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3213 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3218 mymiplevel = savemiplevel;
3219 if (r_loadnormalmap)
3220 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);
3221 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3223 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3224 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3225 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3226 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3229 // _norm is the name used by tenebrae and has been adopted as standard
3230 if (r_loadnormalmap && skinframe->nmap == NULL)
3232 mymiplevel = savemiplevel;
3233 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3235 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3239 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3241 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3242 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3243 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3245 Mem_Free(bumppixels);
3247 else if (r_shadow_bumpscale_basetexture.value > 0)
3249 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3250 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3251 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);
3254 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3255 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3258 // _luma is supported only for tenebrae compatibility
3259 // _glow is the preferred name
3260 mymiplevel = savemiplevel;
3261 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))))
3263 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);
3264 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3265 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3266 Mem_Free(pixels);pixels = NULL;
3269 mymiplevel = savemiplevel;
3270 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3272 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);
3273 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3274 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3279 mymiplevel = savemiplevel;
3280 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3282 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);
3283 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3284 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3289 mymiplevel = savemiplevel;
3290 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3292 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);
3293 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3294 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3299 mymiplevel = savemiplevel;
3300 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3302 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);
3303 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3304 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3310 Mem_Free(basepixels);
3315 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3316 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3319 unsigned char *temp1, *temp2;
3320 skinframe_t *skinframe;
3322 if (cls.state == ca_dedicated)
3325 // if already loaded just return it, otherwise make a new skinframe
3326 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3327 if (skinframe && skinframe->base)
3330 skinframe->stain = NULL;
3331 skinframe->merged = NULL;
3332 skinframe->base = NULL;
3333 skinframe->pants = NULL;
3334 skinframe->shirt = NULL;
3335 skinframe->nmap = NULL;
3336 skinframe->gloss = NULL;
3337 skinframe->glow = NULL;
3338 skinframe->fog = NULL;
3339 skinframe->reflect = NULL;
3340 skinframe->hasalpha = false;
3342 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3346 if (developer_loading.integer)
3347 Con_Printf("loading 32bit skin \"%s\"\n", name);
3349 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3351 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3352 temp2 = temp1 + width * height * 4;
3353 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3354 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);
3357 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3358 if (textureflags & TEXF_ALPHA)
3360 for (i = 3;i < width * height * 4;i += 4)
3362 if (skindata[i] < 255)
3364 skinframe->hasalpha = true;
3368 if (r_loadfog && skinframe->hasalpha)
3370 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3371 memcpy(fogpixels, skindata, width * height * 4);
3372 for (i = 0;i < width * height * 4;i += 4)
3373 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3374 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3375 Mem_Free(fogpixels);
3379 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3380 //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]);
3385 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3389 skinframe_t *skinframe;
3391 if (cls.state == ca_dedicated)
3394 // if already loaded just return it, otherwise make a new skinframe
3395 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3396 if (skinframe && skinframe->base)
3399 skinframe->stain = NULL;
3400 skinframe->merged = NULL;
3401 skinframe->base = NULL;
3402 skinframe->pants = NULL;
3403 skinframe->shirt = NULL;
3404 skinframe->nmap = NULL;
3405 skinframe->gloss = NULL;
3406 skinframe->glow = NULL;
3407 skinframe->fog = NULL;
3408 skinframe->reflect = NULL;
3409 skinframe->hasalpha = false;
3411 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3415 if (developer_loading.integer)
3416 Con_Printf("loading quake skin \"%s\"\n", name);
3418 // 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)
3419 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3420 memcpy(skinframe->qpixels, skindata, width*height);
3421 skinframe->qwidth = width;
3422 skinframe->qheight = height;
3425 for (i = 0;i < width * height;i++)
3426 featuresmask |= palette_featureflags[skindata[i]];
3428 skinframe->hasalpha = false;
3429 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3430 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3431 skinframe->qgeneratemerged = true;
3432 skinframe->qgeneratebase = skinframe->qhascolormapping;
3433 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3435 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3436 //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]);
3441 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3445 unsigned char *skindata;
3447 if (!skinframe->qpixels)
3450 if (!skinframe->qhascolormapping)
3451 colormapped = false;
3455 if (!skinframe->qgeneratebase)
3460 if (!skinframe->qgeneratemerged)
3464 width = skinframe->qwidth;
3465 height = skinframe->qheight;
3466 skindata = skinframe->qpixels;
3468 if (skinframe->qgeneratenmap)
3470 unsigned char *temp1, *temp2;
3471 skinframe->qgeneratenmap = false;
3472 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3473 temp2 = temp1 + width * height * 4;
3474 // use either a custom palette or the quake palette
3475 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3476 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3477 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);
3481 if (skinframe->qgenerateglow)
3483 skinframe->qgenerateglow = false;
3484 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3489 skinframe->qgeneratebase = false;
3490 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);
3491 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3492 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3496 skinframe->qgeneratemerged = false;
3497 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);
3500 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3502 Mem_Free(skinframe->qpixels);
3503 skinframe->qpixels = NULL;
3507 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)
3510 skinframe_t *skinframe;
3512 if (cls.state == ca_dedicated)
3515 // if already loaded just return it, otherwise make a new skinframe
3516 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3517 if (skinframe && skinframe->base)
3520 skinframe->stain = NULL;
3521 skinframe->merged = NULL;
3522 skinframe->base = NULL;
3523 skinframe->pants = NULL;
3524 skinframe->shirt = NULL;
3525 skinframe->nmap = NULL;
3526 skinframe->gloss = NULL;
3527 skinframe->glow = NULL;
3528 skinframe->fog = NULL;
3529 skinframe->reflect = NULL;
3530 skinframe->hasalpha = false;
3532 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3536 if (developer_loading.integer)
3537 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3539 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3540 if (textureflags & TEXF_ALPHA)
3542 for (i = 0;i < width * height;i++)
3544 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3546 skinframe->hasalpha = true;
3550 if (r_loadfog && skinframe->hasalpha)
3551 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3554 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3555 //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]);
3560 skinframe_t *R_SkinFrame_LoadMissing(void)
3562 skinframe_t *skinframe;
3564 if (cls.state == ca_dedicated)
3567 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3568 skinframe->stain = NULL;
3569 skinframe->merged = NULL;
3570 skinframe->base = NULL;
3571 skinframe->pants = NULL;
3572 skinframe->shirt = NULL;
3573 skinframe->nmap = NULL;
3574 skinframe->gloss = NULL;
3575 skinframe->glow = NULL;
3576 skinframe->fog = NULL;
3577 skinframe->reflect = NULL;
3578 skinframe->hasalpha = false;
3580 skinframe->avgcolor[0] = rand() / RAND_MAX;
3581 skinframe->avgcolor[1] = rand() / RAND_MAX;
3582 skinframe->avgcolor[2] = rand() / RAND_MAX;
3583 skinframe->avgcolor[3] = 1;
3588 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3589 typedef struct suffixinfo_s
3592 qboolean flipx, flipy, flipdiagonal;
3595 static suffixinfo_t suffix[3][6] =
3598 {"px", false, false, false},
3599 {"nx", false, false, false},
3600 {"py", false, false, false},
3601 {"ny", false, false, false},
3602 {"pz", false, false, false},
3603 {"nz", false, false, false}
3606 {"posx", false, false, false},
3607 {"negx", false, false, false},
3608 {"posy", false, false, false},
3609 {"negy", false, false, false},
3610 {"posz", false, false, false},
3611 {"negz", false, false, false}
3614 {"rt", true, false, true},
3615 {"lf", false, true, true},
3616 {"ft", true, true, false},
3617 {"bk", false, false, false},
3618 {"up", true, false, true},
3619 {"dn", true, false, true}
3623 static int componentorder[4] = {0, 1, 2, 3};
3625 rtexture_t *R_LoadCubemap(const char *basename)
3627 int i, j, cubemapsize;
3628 unsigned char *cubemappixels, *image_buffer;
3629 rtexture_t *cubemaptexture;
3631 // must start 0 so the first loadimagepixels has no requested width/height
3633 cubemappixels = NULL;
3634 cubemaptexture = NULL;
3635 // keep trying different suffix groups (posx, px, rt) until one loads
3636 for (j = 0;j < 3 && !cubemappixels;j++)
3638 // load the 6 images in the suffix group
3639 for (i = 0;i < 6;i++)
3641 // generate an image name based on the base and and suffix
3642 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3644 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3646 // an image loaded, make sure width and height are equal
3647 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3649 // if this is the first image to load successfully, allocate the cubemap memory
3650 if (!cubemappixels && image_width >= 1)
3652 cubemapsize = image_width;
3653 // note this clears to black, so unavailable sides are black
3654 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3656 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3658 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);
3661 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3663 Mem_Free(image_buffer);
3667 // if a cubemap loaded, upload it
3670 if (developer_loading.integer)
3671 Con_Printf("loading cubemap \"%s\"\n", basename);
3673 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3674 Mem_Free(cubemappixels);
3678 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3679 if (developer_loading.integer)
3681 Con_Printf("(tried tried images ");
3682 for (j = 0;j < 3;j++)
3683 for (i = 0;i < 6;i++)
3684 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3685 Con_Print(" and was unable to find any of them).\n");
3688 return cubemaptexture;
3691 rtexture_t *R_GetCubemap(const char *basename)
3694 for (i = 0;i < r_texture_numcubemaps;i++)
3695 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3696 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3697 if (i >= MAX_CUBEMAPS)
3698 return r_texture_whitecube;
3699 r_texture_numcubemaps++;
3700 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3701 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3702 return r_texture_cubemaps[i].texture;
3705 void R_FreeCubemaps(void)
3708 for (i = 0;i < r_texture_numcubemaps;i++)
3710 if (developer_loading.integer)
3711 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3712 if (r_texture_cubemaps[i].texture)
3713 R_FreeTexture(r_texture_cubemaps[i].texture);
3715 r_texture_numcubemaps = 0;
3718 void R_Main_FreeViewCache(void)
3720 if (r_refdef.viewcache.entityvisible)
3721 Mem_Free(r_refdef.viewcache.entityvisible);
3722 if (r_refdef.viewcache.world_pvsbits)
3723 Mem_Free(r_refdef.viewcache.world_pvsbits);
3724 if (r_refdef.viewcache.world_leafvisible)
3725 Mem_Free(r_refdef.viewcache.world_leafvisible);
3726 if (r_refdef.viewcache.world_surfacevisible)
3727 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3728 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3731 void R_Main_ResizeViewCache(void)
3733 int numentities = r_refdef.scene.numentities;
3734 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3735 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3736 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3737 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3738 if (r_refdef.viewcache.maxentities < numentities)
3740 r_refdef.viewcache.maxentities = numentities;
3741 if (r_refdef.viewcache.entityvisible)
3742 Mem_Free(r_refdef.viewcache.entityvisible);
3743 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3745 if (r_refdef.viewcache.world_numclusters != numclusters)
3747 r_refdef.viewcache.world_numclusters = numclusters;
3748 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3749 if (r_refdef.viewcache.world_pvsbits)
3750 Mem_Free(r_refdef.viewcache.world_pvsbits);
3751 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3753 if (r_refdef.viewcache.world_numleafs != numleafs)
3755 r_refdef.viewcache.world_numleafs = numleafs;
3756 if (r_refdef.viewcache.world_leafvisible)
3757 Mem_Free(r_refdef.viewcache.world_leafvisible);
3758 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3760 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3762 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3763 if (r_refdef.viewcache.world_surfacevisible)
3764 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3765 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3769 extern rtexture_t *loadingscreentexture;
3770 void gl_main_start(void)
3772 loadingscreentexture = NULL;
3773 r_texture_blanknormalmap = NULL;
3774 r_texture_white = NULL;
3775 r_texture_grey128 = NULL;
3776 r_texture_black = NULL;
3777 r_texture_whitecube = NULL;
3778 r_texture_normalizationcube = NULL;
3779 r_texture_fogattenuation = NULL;
3780 r_texture_fogheighttexture = NULL;
3781 r_texture_gammaramps = NULL;
3782 r_texture_numcubemaps = 0;
3784 r_loaddds = r_texture_dds_load.integer != 0;
3785 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3787 switch(vid.renderpath)
3789 case RENDERPATH_GL20:
3790 case RENDERPATH_D3D9:
3791 case RENDERPATH_D3D10:
3792 case RENDERPATH_D3D11:
3793 case RENDERPATH_SOFT:
3794 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3795 Cvar_SetValueQuick(&gl_combine, 1);
3796 Cvar_SetValueQuick(&r_glsl, 1);
3797 r_loadnormalmap = true;
3801 case RENDERPATH_GL13:
3802 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3803 Cvar_SetValueQuick(&gl_combine, 1);
3804 Cvar_SetValueQuick(&r_glsl, 0);
3805 r_loadnormalmap = false;
3806 r_loadgloss = false;
3809 case RENDERPATH_GL11:
3810 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3811 Cvar_SetValueQuick(&gl_combine, 0);
3812 Cvar_SetValueQuick(&r_glsl, 0);
3813 r_loadnormalmap = false;
3814 r_loadgloss = false;
3817 case RENDERPATH_GLES2:
3818 Cvar_SetValueQuick(&r_textureunits, 1);
3819 Cvar_SetValueQuick(&gl_combine, 1);
3820 Cvar_SetValueQuick(&r_glsl, 1);
3821 r_loadnormalmap = true;
3822 r_loadgloss = false;
3828 R_FrameData_Reset();
3832 memset(r_queries, 0, sizeof(r_queries));
3834 r_qwskincache = NULL;
3835 r_qwskincache_size = 0;
3837 // set up r_skinframe loading system for textures
3838 memset(&r_skinframe, 0, sizeof(r_skinframe));
3839 r_skinframe.loadsequence = 1;
3840 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3842 r_main_texturepool = R_AllocTexturePool();
3843 R_BuildBlankTextures();
3845 if (vid.support.arb_texture_cube_map)
3848 R_BuildNormalizationCube();
3850 r_texture_fogattenuation = NULL;
3851 r_texture_fogheighttexture = NULL;
3852 r_texture_gammaramps = NULL;
3853 //r_texture_fogintensity = NULL;
3854 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3855 memset(&r_waterstate, 0, sizeof(r_waterstate));
3856 r_glsl_permutation = NULL;
3857 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3858 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3859 glslshaderstring = NULL;
3861 r_hlsl_permutation = NULL;
3862 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3863 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3865 hlslshaderstring = NULL;
3866 memset(&r_svbsp, 0, sizeof (r_svbsp));
3868 r_refdef.fogmasktable_density = 0;
3871 void gl_main_shutdown(void)
3874 R_FrameData_Reset();
3876 R_Main_FreeViewCache();
3878 switch(vid.renderpath)
3880 case RENDERPATH_GL11:
3881 case RENDERPATH_GL13:
3882 case RENDERPATH_GL20:
3883 case RENDERPATH_GLES2:
3885 qglDeleteQueriesARB(r_maxqueries, r_queries);
3887 case RENDERPATH_D3D9:
3888 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3890 case RENDERPATH_D3D10:
3891 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3893 case RENDERPATH_D3D11:
3894 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3896 case RENDERPATH_SOFT:
3902 memset(r_queries, 0, sizeof(r_queries));
3904 r_qwskincache = NULL;
3905 r_qwskincache_size = 0;
3907 // clear out the r_skinframe state
3908 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3909 memset(&r_skinframe, 0, sizeof(r_skinframe));
3912 Mem_Free(r_svbsp.nodes);
3913 memset(&r_svbsp, 0, sizeof (r_svbsp));
3914 R_FreeTexturePool(&r_main_texturepool);
3915 loadingscreentexture = NULL;
3916 r_texture_blanknormalmap = NULL;
3917 r_texture_white = NULL;
3918 r_texture_grey128 = NULL;
3919 r_texture_black = NULL;
3920 r_texture_whitecube = NULL;
3921 r_texture_normalizationcube = NULL;
3922 r_texture_fogattenuation = NULL;
3923 r_texture_fogheighttexture = NULL;
3924 r_texture_gammaramps = NULL;
3925 r_texture_numcubemaps = 0;
3926 //r_texture_fogintensity = NULL;
3927 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3928 memset(&r_waterstate, 0, sizeof(r_waterstate));
3931 r_glsl_permutation = NULL;
3932 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3933 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3934 glslshaderstring = NULL;
3936 r_hlsl_permutation = NULL;
3937 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3938 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3940 hlslshaderstring = NULL;
3943 extern void CL_ParseEntityLump(char *entitystring);
3944 void gl_main_newmap(void)
3946 // FIXME: move this code to client
3947 char *entities, entname[MAX_QPATH];
3949 Mem_Free(r_qwskincache);
3950 r_qwskincache = NULL;
3951 r_qwskincache_size = 0;
3954 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3955 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3957 CL_ParseEntityLump(entities);
3961 if (cl.worldmodel->brush.entities)
3962 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3964 R_Main_FreeViewCache();
3966 R_FrameData_Reset();
3969 void GL_Main_Init(void)
3971 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3973 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3974 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3975 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3976 if (gamemode == GAME_NEHAHRA)
3978 Cvar_RegisterVariable (&gl_fogenable);
3979 Cvar_RegisterVariable (&gl_fogdensity);
3980 Cvar_RegisterVariable (&gl_fogred);
3981 Cvar_RegisterVariable (&gl_foggreen);
3982 Cvar_RegisterVariable (&gl_fogblue);
3983 Cvar_RegisterVariable (&gl_fogstart);
3984 Cvar_RegisterVariable (&gl_fogend);
3985 Cvar_RegisterVariable (&gl_skyclip);
3987 Cvar_RegisterVariable(&r_motionblur);
3988 Cvar_RegisterVariable(&r_motionblur_maxblur);
3989 Cvar_RegisterVariable(&r_motionblur_bmin);
3990 Cvar_RegisterVariable(&r_motionblur_vmin);
3991 Cvar_RegisterVariable(&r_motionblur_vmax);
3992 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3993 Cvar_RegisterVariable(&r_motionblur_randomize);
3994 Cvar_RegisterVariable(&r_damageblur);
3995 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3996 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3997 Cvar_RegisterVariable(&r_equalize_entities_by);
3998 Cvar_RegisterVariable(&r_equalize_entities_to);
3999 Cvar_RegisterVariable(&r_depthfirst);
4000 Cvar_RegisterVariable(&r_useinfinitefarclip);
4001 Cvar_RegisterVariable(&r_farclip_base);
4002 Cvar_RegisterVariable(&r_farclip_world);
4003 Cvar_RegisterVariable(&r_nearclip);
4004 Cvar_RegisterVariable(&r_showbboxes);
4005 Cvar_RegisterVariable(&r_showsurfaces);
4006 Cvar_RegisterVariable(&r_showtris);
4007 Cvar_RegisterVariable(&r_shownormals);
4008 Cvar_RegisterVariable(&r_showlighting);
4009 Cvar_RegisterVariable(&r_showshadowvolumes);
4010 Cvar_RegisterVariable(&r_showcollisionbrushes);
4011 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4012 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4013 Cvar_RegisterVariable(&r_showdisabledepthtest);
4014 Cvar_RegisterVariable(&r_drawportals);
4015 Cvar_RegisterVariable(&r_drawentities);
4016 Cvar_RegisterVariable(&r_draw2d);
4017 Cvar_RegisterVariable(&r_drawworld);
4018 Cvar_RegisterVariable(&r_cullentities_trace);
4019 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4020 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4021 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4022 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4023 Cvar_RegisterVariable(&r_drawviewmodel);
4024 Cvar_RegisterVariable(&r_drawexteriormodel);
4025 Cvar_RegisterVariable(&r_speeds);
4026 Cvar_RegisterVariable(&r_fullbrights);
4027 Cvar_RegisterVariable(&r_wateralpha);
4028 Cvar_RegisterVariable(&r_dynamic);
4029 Cvar_RegisterVariable(&r_fakelight);
4030 Cvar_RegisterVariable(&r_fakelight_intensity);
4031 Cvar_RegisterVariable(&r_fullbright);
4032 Cvar_RegisterVariable(&r_shadows);
4033 Cvar_RegisterVariable(&r_shadows_darken);
4034 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4035 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4036 Cvar_RegisterVariable(&r_shadows_throwdistance);
4037 Cvar_RegisterVariable(&r_shadows_throwdirection);
4038 Cvar_RegisterVariable(&r_shadows_focus);
4039 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4040 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4041 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4042 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4043 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4044 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4045 Cvar_RegisterVariable(&r_fog_exp2);
4046 Cvar_RegisterVariable(&r_drawfog);
4047 Cvar_RegisterVariable(&r_transparentdepthmasking);
4048 Cvar_RegisterVariable(&r_texture_dds_load);
4049 Cvar_RegisterVariable(&r_texture_dds_save);
4050 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4051 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4052 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4053 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4054 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4055 Cvar_RegisterVariable(&r_textureunits);
4056 Cvar_RegisterVariable(&gl_combine);
4057 Cvar_RegisterVariable(&r_glsl);
4058 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4059 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4060 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4061 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4062 Cvar_RegisterVariable(&r_glsl_postprocess);
4063 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4064 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4065 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4066 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4067 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4068 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4069 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4070 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4072 Cvar_RegisterVariable(&r_water);
4073 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4074 Cvar_RegisterVariable(&r_water_clippingplanebias);
4075 Cvar_RegisterVariable(&r_water_refractdistort);
4076 Cvar_RegisterVariable(&r_water_reflectdistort);
4077 Cvar_RegisterVariable(&r_water_scissormode);
4078 Cvar_RegisterVariable(&r_lerpsprites);
4079 Cvar_RegisterVariable(&r_lerpmodels);
4080 Cvar_RegisterVariable(&r_lerplightstyles);
4081 Cvar_RegisterVariable(&r_waterscroll);
4082 Cvar_RegisterVariable(&r_bloom);
4083 Cvar_RegisterVariable(&r_bloom_colorscale);
4084 Cvar_RegisterVariable(&r_bloom_brighten);
4085 Cvar_RegisterVariable(&r_bloom_blur);
4086 Cvar_RegisterVariable(&r_bloom_resolution);
4087 Cvar_RegisterVariable(&r_bloom_colorexponent);
4088 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4089 Cvar_RegisterVariable(&r_hdr);
4090 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4091 Cvar_RegisterVariable(&r_hdr_glowintensity);
4092 Cvar_RegisterVariable(&r_hdr_range);
4093 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4094 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4095 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4096 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4097 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4098 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4099 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4100 Cvar_RegisterVariable(&developer_texturelogging);
4101 Cvar_RegisterVariable(&gl_lightmaps);
4102 Cvar_RegisterVariable(&r_test);
4103 Cvar_RegisterVariable(&r_glsl_saturation);
4104 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4105 Cvar_RegisterVariable(&r_framedatasize);
4106 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4107 Cvar_SetValue("r_fullbrights", 0);
4108 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4110 Cvar_RegisterVariable(&r_track_sprites);
4111 Cvar_RegisterVariable(&r_track_sprites_flags);
4112 Cvar_RegisterVariable(&r_track_sprites_scalew);
4113 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4114 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4115 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4116 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4117 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4120 extern void R_Textures_Init(void);
4121 extern void GL_Draw_Init(void);
4122 extern void GL_Main_Init(void);
4123 extern void R_Shadow_Init(void);
4124 extern void R_Sky_Init(void);
4125 extern void GL_Surf_Init(void);
4126 extern void R_Particles_Init(void);
4127 extern void R_Explosion_Init(void);
4128 extern void gl_backend_init(void);
4129 extern void Sbar_Init(void);
4130 extern void R_LightningBeams_Init(void);
4131 extern void Mod_RenderInit(void);
4132 extern void Font_Init(void);
4134 void Render_Init(void)
4147 R_LightningBeams_Init();
4156 extern char *ENGINE_EXTENSIONS;
4159 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4160 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4161 gl_version = (const char *)qglGetString(GL_VERSION);
4162 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4166 if (!gl_platformextensions)
4167 gl_platformextensions = "";
4169 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4170 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4171 Con_Printf("GL_VERSION: %s\n", gl_version);
4172 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4173 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4175 VID_CheckExtensions();
4177 // LordHavoc: report supported extensions
4178 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4180 // clear to black (loading plaque will be seen over this)
4181 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4184 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4188 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4190 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4193 p = r_refdef.view.frustum + i;
4198 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4202 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4206 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4210 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4214 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4218 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4222 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4226 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4234 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4238 for (i = 0;i < numplanes;i++)
4245 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4249 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4253 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4257 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4261 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4265 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4269 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4273 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4281 //==================================================================================
4283 // LordHavoc: this stores temporary data used within the same frame
4285 typedef struct r_framedata_mem_s
4287 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4288 size_t size; // how much usable space
4289 size_t current; // how much space in use
4290 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4291 size_t wantedsize; // how much space was allocated
4292 unsigned char *data; // start of real data (16byte aligned)
4296 static r_framedata_mem_t *r_framedata_mem;
4298 void R_FrameData_Reset(void)
4300 while (r_framedata_mem)
4302 r_framedata_mem_t *next = r_framedata_mem->purge;
4303 Mem_Free(r_framedata_mem);
4304 r_framedata_mem = next;
4308 void R_FrameData_Resize(void)
4311 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4312 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4313 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4315 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4316 newmem->wantedsize = wantedsize;
4317 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4318 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4319 newmem->current = 0;
4321 newmem->purge = r_framedata_mem;
4322 r_framedata_mem = newmem;
4326 void R_FrameData_NewFrame(void)
4328 R_FrameData_Resize();
4329 if (!r_framedata_mem)
4331 // if we ran out of space on the last frame, free the old memory now
4332 while (r_framedata_mem->purge)
4334 // repeatedly remove the second item in the list, leaving only head
4335 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4336 Mem_Free(r_framedata_mem->purge);
4337 r_framedata_mem->purge = next;
4339 // reset the current mem pointer
4340 r_framedata_mem->current = 0;
4341 r_framedata_mem->mark = 0;
4344 void *R_FrameData_Alloc(size_t size)
4348 // align to 16 byte boundary - the data pointer is already aligned, so we
4349 // only need to ensure the size of every allocation is also aligned
4350 size = (size + 15) & ~15;
4352 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4354 // emergency - we ran out of space, allocate more memory
4355 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4356 R_FrameData_Resize();
4359 data = r_framedata_mem->data + r_framedata_mem->current;
4360 r_framedata_mem->current += size;
4362 // count the usage for stats
4363 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4364 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4366 return (void *)data;
4369 void *R_FrameData_Store(size_t size, void *data)
4371 void *d = R_FrameData_Alloc(size);
4373 memcpy(d, data, size);
4377 void R_FrameData_SetMark(void)
4379 if (!r_framedata_mem)
4381 r_framedata_mem->mark = r_framedata_mem->current;
4384 void R_FrameData_ReturnToMark(void)
4386 if (!r_framedata_mem)
4388 r_framedata_mem->current = r_framedata_mem->mark;
4391 //==================================================================================
4393 // LordHavoc: animcache originally written by Echon, rewritten since then
4396 * Animation cache prevents re-generating mesh data for an animated model
4397 * multiple times in one frame for lighting, shadowing, reflections, etc.
4400 void R_AnimCache_Free(void)
4404 void R_AnimCache_ClearCache(void)
4407 entity_render_t *ent;
4409 for (i = 0;i < r_refdef.scene.numentities;i++)
4411 ent = r_refdef.scene.entities[i];
4412 ent->animcache_vertex3f = NULL;
4413 ent->animcache_normal3f = NULL;
4414 ent->animcache_svector3f = NULL;
4415 ent->animcache_tvector3f = NULL;
4416 ent->animcache_vertexmesh = NULL;
4417 ent->animcache_vertex3fbuffer = NULL;
4418 ent->animcache_vertexmeshbuffer = NULL;
4422 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4426 // check if we need the meshbuffers
4427 if (!vid.useinterleavedarrays)
4430 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4431 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4432 // TODO: upload vertex3f buffer?
4433 if (ent->animcache_vertexmesh)
4435 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4436 for (i = 0;i < numvertices;i++)
4437 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4438 if (ent->animcache_svector3f)
4439 for (i = 0;i < numvertices;i++)
4440 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4441 if (ent->animcache_tvector3f)
4442 for (i = 0;i < numvertices;i++)
4443 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4444 if (ent->animcache_normal3f)
4445 for (i = 0;i < numvertices;i++)
4446 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4447 // TODO: upload vertexmeshbuffer?
4451 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4453 dp_model_t *model = ent->model;
4455 // see if it's already cached this frame
4456 if (ent->animcache_vertex3f)
4458 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4459 if (wantnormals || wanttangents)
4461 if (ent->animcache_normal3f)
4462 wantnormals = false;
4463 if (ent->animcache_svector3f)
4464 wanttangents = false;
4465 if (wantnormals || wanttangents)
4467 numvertices = model->surfmesh.num_vertices;
4469 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4472 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4473 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4475 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4476 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4482 // see if this ent is worth caching
4483 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4485 // get some memory for this entity and generate mesh data
4486 numvertices = model->surfmesh.num_vertices;
4487 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4489 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4492 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4493 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4495 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4496 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4501 void R_AnimCache_CacheVisibleEntities(void)
4504 qboolean wantnormals = true;
4505 qboolean wanttangents = !r_showsurfaces.integer;
4507 switch(vid.renderpath)
4509 case RENDERPATH_GL20:
4510 case RENDERPATH_D3D9:
4511 case RENDERPATH_D3D10:
4512 case RENDERPATH_D3D11:
4513 case RENDERPATH_GLES2:
4515 case RENDERPATH_GL13:
4516 case RENDERPATH_GL11:
4517 wanttangents = false;
4519 case RENDERPATH_SOFT:
4523 if (r_shownormals.integer)
4524 wanttangents = wantnormals = true;
4526 // TODO: thread this
4527 // NOTE: R_PrepareRTLights() also caches entities
4529 for (i = 0;i < r_refdef.scene.numentities;i++)
4530 if (r_refdef.viewcache.entityvisible[i])
4531 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4534 //==================================================================================
4536 static void R_View_UpdateEntityLighting (void)
4539 entity_render_t *ent;
4540 vec3_t tempdiffusenormal, avg;
4541 vec_t f, fa, fd, fdd;
4542 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4544 for (i = 0;i < r_refdef.scene.numentities;i++)
4546 ent = r_refdef.scene.entities[i];
4548 // skip unseen models
4549 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4553 if (ent->model && ent->model->brush.num_leafs)
4555 // TODO: use modellight for r_ambient settings on world?
4556 VectorSet(ent->modellight_ambient, 0, 0, 0);
4557 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4558 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4562 // fetch the lighting from the worldmodel data
4563 VectorClear(ent->modellight_ambient);
4564 VectorClear(ent->modellight_diffuse);
4565 VectorClear(tempdiffusenormal);
4566 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4569 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4571 // complete lightning for lit sprites
4572 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4573 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4575 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4576 org[2] = org[2] + r_overheadsprites_pushback.value;
4577 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4580 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4582 if(ent->flags & RENDER_EQUALIZE)
4584 // first fix up ambient lighting...
4585 if(r_equalize_entities_minambient.value > 0)
4587 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4590 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4591 if(fa < r_equalize_entities_minambient.value * fd)
4594 // fa'/fd' = minambient
4595 // fa'+0.25*fd' = fa+0.25*fd
4597 // fa' = fd' * minambient
4598 // fd'*(0.25+minambient) = fa+0.25*fd
4600 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4601 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4603 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4604 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
4605 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4606 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4611 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4613 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4614 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4618 // adjust brightness and saturation to target
4619 avg[0] = avg[1] = avg[2] = fa / f;
4620 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4621 avg[0] = avg[1] = avg[2] = fd / f;
4622 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4628 VectorSet(ent->modellight_ambient, 1, 1, 1);
4630 // move the light direction into modelspace coordinates for lighting code
4631 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4632 if(VectorLength2(ent->modellight_lightdir) == 0)
4633 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4634 VectorNormalize(ent->modellight_lightdir);
4638 #define MAX_LINEOFSIGHTTRACES 64
4640 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4643 vec3_t boxmins, boxmaxs;
4646 dp_model_t *model = r_refdef.scene.worldmodel;
4648 if (!model || !model->brush.TraceLineOfSight)
4651 // expand the box a little
4652 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4653 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4654 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4655 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4656 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4657 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4659 // return true if eye is inside enlarged box
4660 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4664 VectorCopy(eye, start);
4665 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4666 if (model->brush.TraceLineOfSight(model, start, end))
4669 // try various random positions
4670 for (i = 0;i < numsamples;i++)
4672 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4673 if (model->brush.TraceLineOfSight(model, start, end))
4681 static void R_View_UpdateEntityVisible (void)
4686 entity_render_t *ent;
4688 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4689 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4690 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4691 : RENDER_EXTERIORMODEL;
4692 if (!r_drawviewmodel.integer)
4693 renderimask |= RENDER_VIEWMODEL;
4694 if (!r_drawexteriormodel.integer)
4695 renderimask |= RENDER_EXTERIORMODEL;
4696 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4698 // worldmodel can check visibility
4699 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4700 for (i = 0;i < r_refdef.scene.numentities;i++)
4702 ent = r_refdef.scene.entities[i];
4703 if (!(ent->flags & renderimask))
4704 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)))
4705 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))
4706 r_refdef.viewcache.entityvisible[i] = true;
4708 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4709 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4711 for (i = 0;i < r_refdef.scene.numentities;i++)
4713 ent = r_refdef.scene.entities[i];
4714 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4716 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4718 continue; // temp entities do pvs only
4719 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4720 ent->last_trace_visibility = realtime;
4721 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4722 r_refdef.viewcache.entityvisible[i] = 0;
4729 // no worldmodel or it can't check visibility
4730 for (i = 0;i < r_refdef.scene.numentities;i++)
4732 ent = r_refdef.scene.entities[i];
4733 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));
4738 /// only used if skyrendermasked, and normally returns false
4739 int R_DrawBrushModelsSky (void)
4742 entity_render_t *ent;
4745 for (i = 0;i < r_refdef.scene.numentities;i++)
4747 if (!r_refdef.viewcache.entityvisible[i])
4749 ent = r_refdef.scene.entities[i];
4750 if (!ent->model || !ent->model->DrawSky)
4752 ent->model->DrawSky(ent);
4758 static void R_DrawNoModel(entity_render_t *ent);
4759 static void R_DrawModels(void)
4762 entity_render_t *ent;
4764 for (i = 0;i < r_refdef.scene.numentities;i++)
4766 if (!r_refdef.viewcache.entityvisible[i])
4768 ent = r_refdef.scene.entities[i];
4769 r_refdef.stats.entities++;
4770 if (ent->model && ent->model->Draw != NULL)
4771 ent->model->Draw(ent);
4777 static void R_DrawModelsDepth(void)
4780 entity_render_t *ent;
4782 for (i = 0;i < r_refdef.scene.numentities;i++)
4784 if (!r_refdef.viewcache.entityvisible[i])
4786 ent = r_refdef.scene.entities[i];
4787 if (ent->model && ent->model->DrawDepth != NULL)
4788 ent->model->DrawDepth(ent);
4792 static void R_DrawModelsDebug(void)
4795 entity_render_t *ent;
4797 for (i = 0;i < r_refdef.scene.numentities;i++)
4799 if (!r_refdef.viewcache.entityvisible[i])
4801 ent = r_refdef.scene.entities[i];
4802 if (ent->model && ent->model->DrawDebug != NULL)
4803 ent->model->DrawDebug(ent);
4807 static void R_DrawModelsAddWaterPlanes(void)
4810 entity_render_t *ent;
4812 for (i = 0;i < r_refdef.scene.numentities;i++)
4814 if (!r_refdef.viewcache.entityvisible[i])
4816 ent = r_refdef.scene.entities[i];
4817 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4818 ent->model->DrawAddWaterPlanes(ent);
4822 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4824 if (r_hdr_irisadaptation.integer)
4828 vec3_t diffusenormal;
4833 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4834 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4835 brightness = max(0.0000001f, brightness);
4836 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4837 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4838 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4839 current = r_hdr_irisadaptation_value.value;
4841 current = min(current + adjust, goal);
4842 else if (current > goal)
4843 current = max(current - adjust, goal);
4844 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4845 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4847 else if (r_hdr_irisadaptation_value.value != 1.0f)
4848 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4851 static void R_View_SetFrustum(const int *scissor)
4854 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4855 vec3_t forward, left, up, origin, v;
4859 // flipped x coordinates (because x points left here)
4860 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4861 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4863 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4864 switch(vid.renderpath)
4866 case RENDERPATH_D3D9:
4867 case RENDERPATH_D3D10:
4868 case RENDERPATH_D3D11:
4869 case RENDERPATH_SOFT:
4870 // non-flipped y coordinates
4871 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4872 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4874 case RENDERPATH_GL11:
4875 case RENDERPATH_GL13:
4876 case RENDERPATH_GL20:
4877 case RENDERPATH_GLES2:
4878 // non-flipped y coordinates
4879 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4880 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4885 // we can't trust r_refdef.view.forward and friends in reflected scenes
4886 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4889 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4890 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4891 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4892 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4893 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4894 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4895 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4896 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4897 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4898 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4899 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4900 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4904 zNear = r_refdef.nearclip;
4905 nudge = 1.0 - 1.0 / (1<<23);
4906 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4907 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4908 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4909 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4910 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4911 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4912 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4913 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4919 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4920 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4921 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4922 r_refdef.view.frustum[0].dist = m[15] - m[12];
4924 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4925 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4926 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4927 r_refdef.view.frustum[1].dist = m[15] + m[12];
4929 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4930 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4931 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4932 r_refdef.view.frustum[2].dist = m[15] - m[13];
4934 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4935 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4936 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4937 r_refdef.view.frustum[3].dist = m[15] + m[13];
4939 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4940 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4941 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4942 r_refdef.view.frustum[4].dist = m[15] - m[14];
4944 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4945 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4946 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4947 r_refdef.view.frustum[5].dist = m[15] + m[14];
4950 if (r_refdef.view.useperspective)
4952 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4953 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]);
4954 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]);
4955 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]);
4956 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]);
4958 // then the normals from the corners relative to origin
4959 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4960 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4961 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4962 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4964 // in a NORMAL view, forward cross left == up
4965 // in a REFLECTED view, forward cross left == down
4966 // so our cross products above need to be adjusted for a left handed coordinate system
4967 CrossProduct(forward, left, v);
4968 if(DotProduct(v, up) < 0)
4970 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4971 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
4972 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
4973 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
4976 // Leaving those out was a mistake, those were in the old code, and they
4977 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4978 // I couldn't reproduce it after adding those normalizations. --blub
4979 VectorNormalize(r_refdef.view.frustum[0].normal);
4980 VectorNormalize(r_refdef.view.frustum[1].normal);
4981 VectorNormalize(r_refdef.view.frustum[2].normal);
4982 VectorNormalize(r_refdef.view.frustum[3].normal);
4984 // make the corners absolute
4985 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
4986 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
4987 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
4988 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
4991 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4993 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4994 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4995 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4996 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4997 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5001 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5002 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5003 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5004 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5005 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5006 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5007 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5008 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5009 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5010 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5012 r_refdef.view.numfrustumplanes = 5;
5014 if (r_refdef.view.useclipplane)
5016 r_refdef.view.numfrustumplanes = 6;
5017 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5020 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5021 PlaneClassify(r_refdef.view.frustum + i);
5023 // LordHavoc: note to all quake engine coders, Quake had a special case
5024 // for 90 degrees which assumed a square view (wrong), so I removed it,
5025 // Quake2 has it disabled as well.
5027 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5028 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5029 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5030 //PlaneClassify(&frustum[0]);
5032 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5033 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5034 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5035 //PlaneClassify(&frustum[1]);
5037 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5038 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5039 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5040 //PlaneClassify(&frustum[2]);
5042 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5043 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5044 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5045 //PlaneClassify(&frustum[3]);
5048 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5049 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5050 //PlaneClassify(&frustum[4]);
5053 void R_View_UpdateWithScissor(const int *myscissor)
5055 R_Main_ResizeViewCache();
5056 R_View_SetFrustum(myscissor);
5057 R_View_WorldVisibility(r_refdef.view.useclipplane);
5058 R_View_UpdateEntityVisible();
5059 R_View_UpdateEntityLighting();
5062 void R_View_Update(void)
5064 R_Main_ResizeViewCache();
5065 R_View_SetFrustum(NULL);
5066 R_View_WorldVisibility(r_refdef.view.useclipplane);
5067 R_View_UpdateEntityVisible();
5068 R_View_UpdateEntityLighting();
5071 void R_SetupView(qboolean allowwaterclippingplane)
5073 const float *customclipplane = NULL;
5075 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5077 // LordHavoc: couldn't figure out how to make this approach the
5078 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5079 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5080 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5081 dist = r_refdef.view.clipplane.dist;
5082 plane[0] = r_refdef.view.clipplane.normal[0];
5083 plane[1] = r_refdef.view.clipplane.normal[1];
5084 plane[2] = r_refdef.view.clipplane.normal[2];
5086 customclipplane = plane;
5089 if (!r_refdef.view.useperspective)
5090 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);
5091 else if (vid.stencil && r_useinfinitefarclip.integer)
5092 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);
5094 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);
5095 R_SetViewport(&r_refdef.view.viewport);
5098 void R_EntityMatrix(const matrix4x4_t *matrix)
5100 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5102 gl_modelmatrixchanged = false;
5103 gl_modelmatrix = *matrix;
5104 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5105 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5106 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5107 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5109 switch(vid.renderpath)
5111 case RENDERPATH_D3D9:
5113 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5114 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5117 case RENDERPATH_D3D10:
5118 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5120 case RENDERPATH_D3D11:
5121 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5123 case RENDERPATH_GL13:
5124 case RENDERPATH_GL11:
5125 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5127 case RENDERPATH_SOFT:
5128 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5129 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5131 case RENDERPATH_GL20:
5132 case RENDERPATH_GLES2:
5133 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5134 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5140 void R_ResetViewRendering2D(void)
5142 r_viewport_t viewport;
5145 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5146 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);
5147 R_SetViewport(&viewport);
5148 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5149 GL_Color(1, 1, 1, 1);
5150 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5151 GL_BlendFunc(GL_ONE, GL_ZERO);
5152 GL_ScissorTest(false);
5153 GL_DepthMask(false);
5154 GL_DepthRange(0, 1);
5155 GL_DepthTest(false);
5156 GL_DepthFunc(GL_LEQUAL);
5157 R_EntityMatrix(&identitymatrix);
5158 R_Mesh_ResetTextureState();
5159 GL_PolygonOffset(0, 0);
5160 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5161 switch(vid.renderpath)
5163 case RENDERPATH_GL11:
5164 case RENDERPATH_GL13:
5165 case RENDERPATH_GL20:
5166 case RENDERPATH_GLES2:
5167 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5169 case RENDERPATH_D3D9:
5170 case RENDERPATH_D3D10:
5171 case RENDERPATH_D3D11:
5172 case RENDERPATH_SOFT:
5175 GL_CullFace(GL_NONE);
5178 void R_ResetViewRendering3D(void)
5183 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5184 GL_Color(1, 1, 1, 1);
5185 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5186 GL_BlendFunc(GL_ONE, GL_ZERO);
5187 GL_ScissorTest(true);
5189 GL_DepthRange(0, 1);
5191 GL_DepthFunc(GL_LEQUAL);
5192 R_EntityMatrix(&identitymatrix);
5193 R_Mesh_ResetTextureState();
5194 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5195 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5196 switch(vid.renderpath)
5198 case RENDERPATH_GL11:
5199 case RENDERPATH_GL13:
5200 case RENDERPATH_GL20:
5201 case RENDERPATH_GLES2:
5202 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5204 case RENDERPATH_D3D9:
5205 case RENDERPATH_D3D10:
5206 case RENDERPATH_D3D11:
5207 case RENDERPATH_SOFT:
5210 GL_CullFace(r_refdef.view.cullface_back);
5215 R_RenderView_UpdateViewVectors
5218 static void R_RenderView_UpdateViewVectors(void)
5220 // break apart the view matrix into vectors for various purposes
5221 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5222 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5223 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5224 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5225 // make an inverted copy of the view matrix for tracking sprites
5226 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5229 void R_RenderScene(void);
5230 void R_RenderWaterPlanes(void);
5232 static void R_Water_StartFrame(void)
5235 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5236 r_waterstate_waterplane_t *p;
5238 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5241 switch(vid.renderpath)
5243 case RENDERPATH_GL20:
5244 case RENDERPATH_D3D9:
5245 case RENDERPATH_D3D10:
5246 case RENDERPATH_D3D11:
5247 case RENDERPATH_SOFT:
5248 case RENDERPATH_GLES2:
5250 case RENDERPATH_GL13:
5251 case RENDERPATH_GL11:
5255 // set waterwidth and waterheight to the water resolution that will be
5256 // used (often less than the screen resolution for faster rendering)
5257 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5258 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5260 // calculate desired texture sizes
5261 // can't use water if the card does not support the texture size
5262 if (!r_water.integer || r_showsurfaces.integer)
5263 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5264 else if (vid.support.arb_texture_non_power_of_two)
5266 texturewidth = waterwidth;
5267 textureheight = waterheight;
5268 camerawidth = waterwidth;
5269 cameraheight = waterheight;
5273 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5274 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5275 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5276 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5279 // allocate textures as needed
5280 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5282 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5283 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5285 if (p->texture_refraction)
5286 R_FreeTexture(p->texture_refraction);
5287 p->texture_refraction = NULL;
5288 if (p->texture_reflection)
5289 R_FreeTexture(p->texture_reflection);
5290 p->texture_reflection = NULL;
5291 if (p->texture_camera)
5292 R_FreeTexture(p->texture_camera);
5293 p->texture_camera = NULL;
5295 memset(&r_waterstate, 0, sizeof(r_waterstate));
5296 r_waterstate.texturewidth = texturewidth;
5297 r_waterstate.textureheight = textureheight;
5298 r_waterstate.camerawidth = camerawidth;
5299 r_waterstate.cameraheight = cameraheight;
5302 if (r_waterstate.texturewidth)
5304 r_waterstate.enabled = true;
5306 // when doing a reduced render (HDR) we want to use a smaller area
5307 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5308 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5310 // set up variables that will be used in shader setup
5311 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5312 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5313 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5314 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5317 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5318 r_waterstate.numwaterplanes = 0;
5321 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5323 int triangleindex, planeindex;
5329 r_waterstate_waterplane_t *p;
5330 texture_t *t = R_GetCurrentTexture(surface->texture);
5332 // just use the first triangle with a valid normal for any decisions
5333 VectorClear(normal);
5334 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5336 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5337 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5338 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5339 TriangleNormal(vert[0], vert[1], vert[2], normal);
5340 if (VectorLength2(normal) >= 0.001)
5344 VectorCopy(normal, plane.normal);
5345 VectorNormalize(plane.normal);
5346 plane.dist = DotProduct(vert[0], plane.normal);
5347 PlaneClassify(&plane);
5348 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5350 // skip backfaces (except if nocullface is set)
5351 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5353 VectorNegate(plane.normal, plane.normal);
5355 PlaneClassify(&plane);
5359 // find a matching plane if there is one
5360 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5361 if(p->camera_entity == t->camera_entity)
5362 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5364 if (planeindex >= r_waterstate.maxwaterplanes)
5365 return; // nothing we can do, out of planes
5367 // if this triangle does not fit any known plane rendered this frame, add one
5368 if (planeindex >= r_waterstate.numwaterplanes)
5370 // store the new plane
5371 r_waterstate.numwaterplanes++;
5373 // clear materialflags and pvs
5374 p->materialflags = 0;
5375 p->pvsvalid = false;
5376 p->camera_entity = t->camera_entity;
5377 VectorCopy(surface->mins, p->mins);
5378 VectorCopy(surface->maxs, p->maxs);
5383 p->mins[0] = min(p->mins[0], surface->mins[0]);
5384 p->mins[1] = min(p->mins[1], surface->mins[1]);
5385 p->mins[2] = min(p->mins[2], surface->mins[2]);
5386 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5387 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5388 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5390 // merge this surface's materialflags into the waterplane
5391 p->materialflags |= t->currentmaterialflags;
5392 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5394 // merge this surface's PVS into the waterplane
5395 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5396 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5397 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5399 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5405 static void R_Water_ProcessPlanes(void)
5408 r_refdef_view_t originalview;
5409 r_refdef_view_t myview;
5411 r_waterstate_waterplane_t *p;
5414 originalview = r_refdef.view;
5416 // make sure enough textures are allocated
5417 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5419 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5421 if (!p->texture_refraction)
5422 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);
5423 if (!p->texture_refraction)
5426 else if (p->materialflags & MATERIALFLAG_CAMERA)
5428 if (!p->texture_camera)
5429 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);
5430 if (!p->texture_camera)
5434 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5436 if (!p->texture_reflection)
5437 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);
5438 if (!p->texture_reflection)
5444 r_refdef.view = originalview;
5445 r_refdef.view.showdebug = false;
5446 r_refdef.view.width = r_waterstate.waterwidth;
5447 r_refdef.view.height = r_waterstate.waterheight;
5448 r_refdef.view.useclipplane = true;
5449 myview = r_refdef.view;
5450 r_waterstate.renderingscene = true;
5451 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5453 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5455 r_refdef.view = myview;
5456 if(r_water_scissormode.integer)
5459 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5460 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5463 // render reflected scene and copy into texture
5464 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5465 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5466 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5467 r_refdef.view.clipplane = p->plane;
5469 // reverse the cullface settings for this render
5470 r_refdef.view.cullface_front = GL_FRONT;
5471 r_refdef.view.cullface_back = GL_BACK;
5472 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5474 r_refdef.view.usecustompvs = true;
5476 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5478 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5481 R_ResetViewRendering3D();
5482 R_ClearScreen(r_refdef.fogenabled);
5483 if(r_water_scissormode.integer & 2)
5484 R_View_UpdateWithScissor(myscissor);
5487 if(r_water_scissormode.integer & 1)
5488 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5491 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);
5494 // render the normal view scene and copy into texture
5495 // (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)
5496 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5498 r_refdef.view = myview;
5499 if(r_water_scissormode.integer)
5502 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5503 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5506 r_waterstate.renderingrefraction = true;
5508 r_refdef.view.clipplane = p->plane;
5509 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5510 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5512 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5514 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5515 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5516 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5517 R_RenderView_UpdateViewVectors();
5518 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5520 r_refdef.view.usecustompvs = true;
5521 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);
5525 PlaneClassify(&r_refdef.view.clipplane);
5527 R_ResetViewRendering3D();
5528 R_ClearScreen(r_refdef.fogenabled);
5529 if(r_water_scissormode.integer & 2)
5530 R_View_UpdateWithScissor(myscissor);
5533 if(r_water_scissormode.integer & 1)
5534 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5537 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);
5538 r_waterstate.renderingrefraction = false;
5540 else if (p->materialflags & MATERIALFLAG_CAMERA)
5542 r_refdef.view = myview;
5544 r_refdef.view.clipplane = p->plane;
5545 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5546 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5548 r_refdef.view.width = r_waterstate.camerawidth;
5549 r_refdef.view.height = r_waterstate.cameraheight;
5550 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5551 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5553 if(p->camera_entity)
5555 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5556 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5559 // note: all of the view is used for displaying... so
5560 // there is no use in scissoring
5562 // reverse the cullface settings for this render
5563 r_refdef.view.cullface_front = GL_FRONT;
5564 r_refdef.view.cullface_back = GL_BACK;
5565 // also reverse the view matrix
5566 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
5567 R_RenderView_UpdateViewVectors();
5568 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5570 r_refdef.view.usecustompvs = true;
5571 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);
5574 // camera needs no clipplane
5575 r_refdef.view.useclipplane = false;
5577 PlaneClassify(&r_refdef.view.clipplane);
5579 R_ResetViewRendering3D();
5580 R_ClearScreen(r_refdef.fogenabled);
5584 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);
5585 r_waterstate.renderingrefraction = false;
5589 r_waterstate.renderingscene = false;
5590 r_refdef.view = originalview;
5591 R_ResetViewRendering3D();
5592 R_ClearScreen(r_refdef.fogenabled);
5596 r_refdef.view = originalview;
5597 r_waterstate.renderingscene = false;
5598 Cvar_SetValueQuick(&r_water, 0);
5599 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5603 void R_Bloom_StartFrame(void)
5605 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5607 switch(vid.renderpath)
5609 case RENDERPATH_GL20:
5610 case RENDERPATH_D3D9:
5611 case RENDERPATH_D3D10:
5612 case RENDERPATH_D3D11:
5613 case RENDERPATH_SOFT:
5614 case RENDERPATH_GLES2:
5616 case RENDERPATH_GL13:
5617 case RENDERPATH_GL11:
5621 // set bloomwidth and bloomheight to the bloom resolution that will be
5622 // used (often less than the screen resolution for faster rendering)
5623 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5624 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5625 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5626 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5627 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5629 // calculate desired texture sizes
5630 if (vid.support.arb_texture_non_power_of_two)
5632 screentexturewidth = r_refdef.view.width;
5633 screentextureheight = r_refdef.view.height;
5634 bloomtexturewidth = r_bloomstate.bloomwidth;
5635 bloomtextureheight = r_bloomstate.bloomheight;
5639 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5640 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5641 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5642 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5645 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))
5647 Cvar_SetValueQuick(&r_hdr, 0);
5648 Cvar_SetValueQuick(&r_bloom, 0);
5649 Cvar_SetValueQuick(&r_motionblur, 0);
5650 Cvar_SetValueQuick(&r_damageblur, 0);
5653 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)))
5654 screentexturewidth = screentextureheight = 0;
5655 if (!r_hdr.integer && !r_bloom.integer)
5656 bloomtexturewidth = bloomtextureheight = 0;
5658 // allocate textures as needed
5659 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5661 if (r_bloomstate.texture_screen)
5662 R_FreeTexture(r_bloomstate.texture_screen);
5663 r_bloomstate.texture_screen = NULL;
5664 r_bloomstate.screentexturewidth = screentexturewidth;
5665 r_bloomstate.screentextureheight = screentextureheight;
5666 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5667 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);
5669 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5671 if (r_bloomstate.texture_bloom)
5672 R_FreeTexture(r_bloomstate.texture_bloom);
5673 r_bloomstate.texture_bloom = NULL;
5674 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5675 r_bloomstate.bloomtextureheight = bloomtextureheight;
5676 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5677 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);
5680 // when doing a reduced render (HDR) we want to use a smaller area
5681 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5682 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5683 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5684 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5685 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5687 // set up a texcoord array for the full resolution screen image
5688 // (we have to keep this around to copy back during final render)
5689 r_bloomstate.screentexcoord2f[0] = 0;
5690 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5691 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5692 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5693 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5694 r_bloomstate.screentexcoord2f[5] = 0;
5695 r_bloomstate.screentexcoord2f[6] = 0;
5696 r_bloomstate.screentexcoord2f[7] = 0;
5698 // set up a texcoord array for the reduced resolution bloom image
5699 // (which will be additive blended over the screen image)
5700 r_bloomstate.bloomtexcoord2f[0] = 0;
5701 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5702 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5703 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5704 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5705 r_bloomstate.bloomtexcoord2f[5] = 0;
5706 r_bloomstate.bloomtexcoord2f[6] = 0;
5707 r_bloomstate.bloomtexcoord2f[7] = 0;
5709 switch(vid.renderpath)
5711 case RENDERPATH_GL11:
5712 case RENDERPATH_GL13:
5713 case RENDERPATH_GL20:
5714 case RENDERPATH_SOFT:
5715 case RENDERPATH_GLES2:
5717 case RENDERPATH_D3D9:
5718 case RENDERPATH_D3D10:
5719 case RENDERPATH_D3D11:
5722 for (i = 0;i < 4;i++)
5724 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5725 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5726 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5727 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5733 if (r_hdr.integer || r_bloom.integer)
5735 r_bloomstate.enabled = true;
5736 r_bloomstate.hdr = r_hdr.integer != 0;
5739 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);
5742 void R_Bloom_CopyBloomTexture(float colorscale)
5744 r_refdef.stats.bloom++;
5746 // scale down screen texture to the bloom texture size
5748 R_SetViewport(&r_bloomstate.viewport);
5749 GL_BlendFunc(GL_ONE, GL_ZERO);
5750 GL_Color(colorscale, colorscale, colorscale, 1);
5751 // 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...
5752 switch(vid.renderpath)
5754 case RENDERPATH_GL11:
5755 case RENDERPATH_GL13:
5756 case RENDERPATH_GL20:
5757 case RENDERPATH_SOFT:
5758 case RENDERPATH_GLES2:
5759 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5761 case RENDERPATH_D3D9:
5762 case RENDERPATH_D3D10:
5763 case RENDERPATH_D3D11:
5764 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5767 // TODO: do boxfilter scale-down in shader?
5768 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5769 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5770 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5772 // we now have a bloom image in the framebuffer
5773 // copy it into the bloom image texture for later processing
5774 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);
5775 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5778 void R_Bloom_CopyHDRTexture(void)
5780 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);
5781 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5784 void R_Bloom_MakeTexture(void)
5787 float xoffset, yoffset, r, brighten;
5789 r_refdef.stats.bloom++;
5791 R_ResetViewRendering2D();
5793 // we have a bloom image in the framebuffer
5795 R_SetViewport(&r_bloomstate.viewport);
5797 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5800 r = bound(0, r_bloom_colorexponent.value / x, 1);
5801 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5803 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5804 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5805 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5806 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5808 // copy the vertically blurred bloom view to a texture
5809 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);
5810 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5813 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5814 brighten = r_bloom_brighten.value;
5816 brighten *= r_hdr_range.value;
5817 brighten = sqrt(brighten);
5819 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5820 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5822 for (dir = 0;dir < 2;dir++)
5824 // blend on at multiple vertical offsets to achieve a vertical blur
5825 // TODO: do offset blends using GLSL
5826 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5827 GL_BlendFunc(GL_ONE, GL_ZERO);
5828 for (x = -range;x <= range;x++)
5830 if (!dir){xoffset = 0;yoffset = x;}
5831 else {xoffset = x;yoffset = 0;}
5832 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5833 yoffset /= (float)r_bloomstate.bloomtextureheight;
5834 // compute a texcoord array with the specified x and y offset
5835 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5836 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5837 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5838 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5839 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5840 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5841 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5842 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5843 // this r value looks like a 'dot' particle, fading sharply to
5844 // black at the edges
5845 // (probably not realistic but looks good enough)
5846 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5847 //r = brighten/(range*2+1);
5848 r = brighten / (range * 2 + 1);
5850 r *= (1 - x*x/(float)(range*range));
5851 GL_Color(r, r, r, 1);
5852 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5853 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5854 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5855 GL_BlendFunc(GL_ONE, GL_ONE);
5858 // copy the vertically blurred bloom view to a texture
5859 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);
5860 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5864 void R_HDR_RenderBloomTexture(void)
5866 int oldwidth, oldheight;
5867 float oldcolorscale;
5868 qboolean oldwaterstate;
5870 oldwaterstate = r_waterstate.enabled;
5871 oldcolorscale = r_refdef.view.colorscale;
5872 oldwidth = r_refdef.view.width;
5873 oldheight = r_refdef.view.height;
5874 r_refdef.view.width = r_bloomstate.bloomwidth;
5875 r_refdef.view.height = r_bloomstate.bloomheight;
5877 if(r_hdr.integer < 2)
5878 r_waterstate.enabled = false;
5880 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5881 // TODO: add exposure compensation features
5882 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5884 r_refdef.view.showdebug = false;
5885 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5887 R_ResetViewRendering3D();
5889 R_ClearScreen(r_refdef.fogenabled);
5890 if (r_timereport_active)
5891 R_TimeReport("HDRclear");
5894 if (r_timereport_active)
5895 R_TimeReport("visibility");
5897 // only do secondary renders with HDR if r_hdr is 2 or higher
5898 r_waterstate.numwaterplanes = 0;
5899 if (r_waterstate.enabled)
5900 R_RenderWaterPlanes();
5902 r_refdef.view.showdebug = true;
5904 r_waterstate.numwaterplanes = 0;
5906 R_ResetViewRendering2D();
5908 R_Bloom_CopyHDRTexture();
5909 R_Bloom_MakeTexture();
5911 // restore the view settings
5912 r_waterstate.enabled = oldwaterstate;
5913 r_refdef.view.width = oldwidth;
5914 r_refdef.view.height = oldheight;
5915 r_refdef.view.colorscale = oldcolorscale;
5917 R_ResetViewRendering3D();
5919 R_ClearScreen(r_refdef.fogenabled);
5920 if (r_timereport_active)
5921 R_TimeReport("viewclear");
5924 static void R_BlendView(void)
5926 unsigned int permutation;
5927 float uservecs[4][4];
5929 switch (vid.renderpath)
5931 case RENDERPATH_GL20:
5932 case RENDERPATH_D3D9:
5933 case RENDERPATH_D3D10:
5934 case RENDERPATH_D3D11:
5935 case RENDERPATH_SOFT:
5936 case RENDERPATH_GLES2:
5938 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5939 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5940 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5941 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5942 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5944 if (r_bloomstate.texture_screen)
5946 // make sure the buffer is available
5947 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5949 R_ResetViewRendering2D();
5951 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5953 // declare variables
5955 static float avgspeed;
5957 speed = VectorLength(cl.movement_velocity);
5959 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5960 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5962 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5963 speed = bound(0, speed, 1);
5964 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5966 // calculate values into a standard alpha
5967 cl.motionbluralpha = 1 - exp(-
5969 (r_motionblur.value * speed / 80)
5971 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5974 max(0.0001, cl.time - cl.oldtime) // fps independent
5977 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5978 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5980 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
5982 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5983 GL_Color(1, 1, 1, cl.motionbluralpha);
5984 switch(vid.renderpath)
5986 case RENDERPATH_GL11:
5987 case RENDERPATH_GL13:
5988 case RENDERPATH_GL20:
5989 case RENDERPATH_SOFT:
5990 case RENDERPATH_GLES2:
5991 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5993 case RENDERPATH_D3D9:
5994 case RENDERPATH_D3D10:
5995 case RENDERPATH_D3D11:
5996 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5999 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6000 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6001 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6005 // copy view into the screen texture
6006 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);
6007 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6009 else if (!r_bloomstate.texture_bloom)
6011 // we may still have to do view tint...
6012 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6014 // apply a color tint to the whole view
6015 R_ResetViewRendering2D();
6016 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6017 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6018 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6019 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6020 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6022 break; // no screen processing, no bloom, skip it
6025 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6027 // render simple bloom effect
6028 // copy the screen and shrink it and darken it for the bloom process
6029 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6030 // make the bloom texture
6031 R_Bloom_MakeTexture();
6034 #if _MSC_VER >= 1400
6035 #define sscanf sscanf_s
6037 memset(uservecs, 0, sizeof(uservecs));
6038 if (r_glsl_postprocess_uservec1_enable.integer)
6039 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6040 if (r_glsl_postprocess_uservec2_enable.integer)
6041 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6042 if (r_glsl_postprocess_uservec3_enable.integer)
6043 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6044 if (r_glsl_postprocess_uservec4_enable.integer)
6045 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6047 R_ResetViewRendering2D();
6048 GL_Color(1, 1, 1, 1);
6049 GL_BlendFunc(GL_ONE, GL_ZERO);
6051 switch(vid.renderpath)
6053 case RENDERPATH_GL20:
6054 case RENDERPATH_GLES2:
6055 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6056 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6057 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6058 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6059 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6060 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]);
6061 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6062 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]);
6063 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]);
6064 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]);
6065 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]);
6066 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6067 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6068 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);
6070 case RENDERPATH_D3D9:
6072 // 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...
6073 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6074 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6075 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6076 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6077 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6078 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6079 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6080 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6081 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6082 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6083 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6084 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6085 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6086 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6089 case RENDERPATH_D3D10:
6090 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6092 case RENDERPATH_D3D11:
6093 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6095 case RENDERPATH_SOFT:
6096 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6097 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6098 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6099 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6100 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6101 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6102 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6103 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6104 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6105 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6106 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6107 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6108 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6109 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6114 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6115 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6117 case RENDERPATH_GL13:
6118 case RENDERPATH_GL11:
6119 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6121 // apply a color tint to the whole view
6122 R_ResetViewRendering2D();
6123 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6124 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6125 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6126 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6127 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6133 matrix4x4_t r_waterscrollmatrix;
6135 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6137 if (r_refdef.fog_density)
6139 r_refdef.fogcolor[0] = r_refdef.fog_red;
6140 r_refdef.fogcolor[1] = r_refdef.fog_green;
6141 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6143 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6144 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6145 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6146 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6150 VectorCopy(r_refdef.fogcolor, fogvec);
6151 // color.rgb *= ContrastBoost * SceneBrightness;
6152 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6153 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6154 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6155 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6160 void R_UpdateVariables(void)
6164 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6166 r_refdef.farclip = r_farclip_base.value;
6167 if (r_refdef.scene.worldmodel)
6168 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6169 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6171 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6172 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6173 r_refdef.polygonfactor = 0;
6174 r_refdef.polygonoffset = 0;
6175 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6176 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6178 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6179 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6180 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6181 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6182 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6183 if (FAKELIGHT_ENABLED)
6185 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6187 if (r_showsurfaces.integer)
6189 r_refdef.scene.rtworld = false;
6190 r_refdef.scene.rtworldshadows = false;
6191 r_refdef.scene.rtdlight = false;
6192 r_refdef.scene.rtdlightshadows = false;
6193 r_refdef.lightmapintensity = 0;
6196 if (gamemode == GAME_NEHAHRA)
6198 if (gl_fogenable.integer)
6200 r_refdef.oldgl_fogenable = true;
6201 r_refdef.fog_density = gl_fogdensity.value;
6202 r_refdef.fog_red = gl_fogred.value;
6203 r_refdef.fog_green = gl_foggreen.value;
6204 r_refdef.fog_blue = gl_fogblue.value;
6205 r_refdef.fog_alpha = 1;
6206 r_refdef.fog_start = 0;
6207 r_refdef.fog_end = gl_skyclip.value;
6208 r_refdef.fog_height = 1<<30;
6209 r_refdef.fog_fadedepth = 128;
6211 else if (r_refdef.oldgl_fogenable)
6213 r_refdef.oldgl_fogenable = false;
6214 r_refdef.fog_density = 0;
6215 r_refdef.fog_red = 0;
6216 r_refdef.fog_green = 0;
6217 r_refdef.fog_blue = 0;
6218 r_refdef.fog_alpha = 0;
6219 r_refdef.fog_start = 0;
6220 r_refdef.fog_end = 0;
6221 r_refdef.fog_height = 1<<30;
6222 r_refdef.fog_fadedepth = 128;
6226 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6227 r_refdef.fog_start = max(0, r_refdef.fog_start);
6228 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6230 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6232 if (r_refdef.fog_density && r_drawfog.integer)
6234 r_refdef.fogenabled = true;
6235 // this is the point where the fog reaches 0.9986 alpha, which we
6236 // consider a good enough cutoff point for the texture
6237 // (0.9986 * 256 == 255.6)
6238 if (r_fog_exp2.integer)
6239 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6241 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6242 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6243 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6244 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6245 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6246 R_BuildFogHeightTexture();
6247 // fog color was already set
6248 // update the fog texture
6249 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)
6250 R_BuildFogTexture();
6251 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6252 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6255 r_refdef.fogenabled = false;
6257 switch(vid.renderpath)
6259 case RENDERPATH_GL20:
6260 case RENDERPATH_D3D9:
6261 case RENDERPATH_D3D10:
6262 case RENDERPATH_D3D11:
6263 case RENDERPATH_SOFT:
6264 case RENDERPATH_GLES2:
6265 if(v_glslgamma.integer && !vid_gammatables_trivial)
6267 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6269 // build GLSL gamma texture
6270 #define RAMPWIDTH 256
6271 unsigned short ramp[RAMPWIDTH * 3];
6272 unsigned char rampbgr[RAMPWIDTH][4];
6275 r_texture_gammaramps_serial = vid_gammatables_serial;
6277 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6278 for(i = 0; i < RAMPWIDTH; ++i)
6280 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6281 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6282 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6285 if (r_texture_gammaramps)
6287 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6291 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6297 // remove GLSL gamma texture
6300 case RENDERPATH_GL13:
6301 case RENDERPATH_GL11:
6306 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6307 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6313 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6314 if( scenetype != r_currentscenetype ) {
6315 // store the old scenetype
6316 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6317 r_currentscenetype = scenetype;
6318 // move in the new scene
6319 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6328 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6330 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6331 if( scenetype == r_currentscenetype ) {
6332 return &r_refdef.scene;
6334 return &r_scenes_store[ scenetype ];
6343 int dpsoftrast_test;
6344 void R_RenderView(void)
6346 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6348 dpsoftrast_test = r_test.integer;
6350 if (r_timereport_active)
6351 R_TimeReport("start");
6352 r_textureframe++; // used only by R_GetCurrentTexture
6353 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6355 if(R_CompileShader_CheckStaticParms())
6358 if (!r_drawentities.integer)
6359 r_refdef.scene.numentities = 0;
6361 R_AnimCache_ClearCache();
6362 R_FrameData_NewFrame();
6364 /* adjust for stereo display */
6365 if(R_Stereo_Active())
6367 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);
6368 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6371 if (r_refdef.view.isoverlay)
6373 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6374 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6375 R_TimeReport("depthclear");
6377 r_refdef.view.showdebug = false;
6379 r_waterstate.enabled = false;
6380 r_waterstate.numwaterplanes = 0;
6384 r_refdef.view.matrix = originalmatrix;
6390 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6392 r_refdef.view.matrix = originalmatrix;
6393 return; //Host_Error ("R_RenderView: NULL worldmodel");
6396 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6398 R_RenderView_UpdateViewVectors();
6400 R_Shadow_UpdateWorldLightSelection();
6402 R_Bloom_StartFrame();
6403 R_Water_StartFrame();
6406 if (r_timereport_active)
6407 R_TimeReport("viewsetup");
6409 R_ResetViewRendering3D();
6411 if (r_refdef.view.clear || r_refdef.fogenabled)
6413 R_ClearScreen(r_refdef.fogenabled);
6414 if (r_timereport_active)
6415 R_TimeReport("viewclear");
6417 r_refdef.view.clear = true;
6419 // this produces a bloom texture to be used in R_BlendView() later
6420 if (r_hdr.integer && r_bloomstate.bloomwidth)
6422 R_HDR_RenderBloomTexture();
6423 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6424 r_textureframe++; // used only by R_GetCurrentTexture
6427 r_refdef.view.showdebug = true;
6430 if (r_timereport_active)
6431 R_TimeReport("visibility");
6433 r_waterstate.numwaterplanes = 0;
6434 if (r_waterstate.enabled)
6435 R_RenderWaterPlanes();
6438 r_waterstate.numwaterplanes = 0;
6441 if (r_timereport_active)
6442 R_TimeReport("blendview");
6444 GL_Scissor(0, 0, vid.width, vid.height);
6445 GL_ScissorTest(false);
6447 r_refdef.view.matrix = originalmatrix;
6452 void R_RenderWaterPlanes(void)
6454 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6456 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6457 if (r_timereport_active)
6458 R_TimeReport("waterworld");
6461 // don't let sound skip if going slow
6462 if (r_refdef.scene.extraupdate)
6465 R_DrawModelsAddWaterPlanes();
6466 if (r_timereport_active)
6467 R_TimeReport("watermodels");
6469 if (r_waterstate.numwaterplanes)
6471 R_Water_ProcessPlanes();
6472 if (r_timereport_active)
6473 R_TimeReport("waterscenes");
6477 extern void R_DrawLightningBeams (void);
6478 extern void VM_CL_AddPolygonsToMeshQueue (void);
6479 extern void R_DrawPortals (void);
6480 extern cvar_t cl_locs_show;
6481 static void R_DrawLocs(void);
6482 static void R_DrawEntityBBoxes(void);
6483 static void R_DrawModelDecals(void);
6484 extern void R_DrawModelShadows(void);
6485 extern void R_DrawModelShadowMaps(void);
6486 extern cvar_t cl_decals_newsystem;
6487 extern qboolean r_shadow_usingdeferredprepass;
6488 void R_RenderScene(void)
6490 qboolean shadowmapping = false;
6492 if (r_timereport_active)
6493 R_TimeReport("beginscene");
6495 r_refdef.stats.renders++;
6499 // don't let sound skip if going slow
6500 if (r_refdef.scene.extraupdate)
6503 R_MeshQueue_BeginScene();
6507 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);
6509 if (r_timereport_active)
6510 R_TimeReport("skystartframe");
6512 if (cl.csqc_vidvars.drawworld)
6514 // don't let sound skip if going slow
6515 if (r_refdef.scene.extraupdate)
6518 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6520 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6521 if (r_timereport_active)
6522 R_TimeReport("worldsky");
6525 if (R_DrawBrushModelsSky() && r_timereport_active)
6526 R_TimeReport("bmodelsky");
6528 if (skyrendermasked && skyrenderlater)
6530 // we have to force off the water clipping plane while rendering sky
6534 if (r_timereport_active)
6535 R_TimeReport("sky");
6539 R_AnimCache_CacheVisibleEntities();
6540 if (r_timereport_active)
6541 R_TimeReport("animation");
6543 R_Shadow_PrepareLights();
6544 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6545 R_Shadow_PrepareModelShadows();
6546 if (r_timereport_active)
6547 R_TimeReport("preparelights");
6549 if (R_Shadow_ShadowMappingEnabled())
6550 shadowmapping = true;
6552 if (r_shadow_usingdeferredprepass)
6553 R_Shadow_DrawPrepass();
6555 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6557 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6558 if (r_timereport_active)
6559 R_TimeReport("worlddepth");
6561 if (r_depthfirst.integer >= 2)
6563 R_DrawModelsDepth();
6564 if (r_timereport_active)
6565 R_TimeReport("modeldepth");
6568 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6570 R_DrawModelShadowMaps();
6571 R_ResetViewRendering3D();
6572 // don't let sound skip if going slow
6573 if (r_refdef.scene.extraupdate)
6577 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6579 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6580 if (r_timereport_active)
6581 R_TimeReport("world");
6584 // don't let sound skip if going slow
6585 if (r_refdef.scene.extraupdate)
6589 if (r_timereport_active)
6590 R_TimeReport("models");
6592 // don't let sound skip if going slow
6593 if (r_refdef.scene.extraupdate)
6596 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6598 R_DrawModelShadows();
6599 R_ResetViewRendering3D();
6600 // don't let sound skip if going slow
6601 if (r_refdef.scene.extraupdate)
6605 if (!r_shadow_usingdeferredprepass)
6607 R_Shadow_DrawLights();
6608 if (r_timereport_active)
6609 R_TimeReport("rtlights");
6612 // don't let sound skip if going slow
6613 if (r_refdef.scene.extraupdate)
6616 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6618 R_DrawModelShadows();
6619 R_ResetViewRendering3D();
6620 // don't let sound skip if going slow
6621 if (r_refdef.scene.extraupdate)
6625 if (cl.csqc_vidvars.drawworld)
6627 if (cl_decals_newsystem.integer)
6629 R_DrawModelDecals();
6630 if (r_timereport_active)
6631 R_TimeReport("modeldecals");
6636 if (r_timereport_active)
6637 R_TimeReport("decals");
6641 if (r_timereport_active)
6642 R_TimeReport("particles");
6645 if (r_timereport_active)
6646 R_TimeReport("explosions");
6648 R_DrawLightningBeams();
6649 if (r_timereport_active)
6650 R_TimeReport("lightning");
6653 VM_CL_AddPolygonsToMeshQueue();
6655 if (r_refdef.view.showdebug)
6657 if (cl_locs_show.integer)
6660 if (r_timereport_active)
6661 R_TimeReport("showlocs");
6664 if (r_drawportals.integer)
6667 if (r_timereport_active)
6668 R_TimeReport("portals");
6671 if (r_showbboxes.value > 0)
6673 R_DrawEntityBBoxes();
6674 if (r_timereport_active)
6675 R_TimeReport("bboxes");
6679 R_MeshQueue_RenderTransparent();
6680 if (r_timereport_active)
6681 R_TimeReport("drawtrans");
6683 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))
6685 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6686 if (r_timereport_active)
6687 R_TimeReport("worlddebug");
6688 R_DrawModelsDebug();
6689 if (r_timereport_active)
6690 R_TimeReport("modeldebug");
6693 if (cl.csqc_vidvars.drawworld)
6695 R_Shadow_DrawCoronas();
6696 if (r_timereport_active)
6697 R_TimeReport("coronas");
6702 GL_DepthTest(false);
6703 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6704 GL_Color(1, 1, 1, 1);
6705 qglBegin(GL_POLYGON);
6706 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6707 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6708 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6709 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6711 qglBegin(GL_POLYGON);
6712 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]);
6713 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]);
6714 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]);
6715 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]);
6717 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6721 // don't let sound skip if going slow
6722 if (r_refdef.scene.extraupdate)
6725 R_ResetViewRendering2D();
6728 static const unsigned short bboxelements[36] =
6738 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6741 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6743 RSurf_ActiveWorldEntity();
6745 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6746 GL_DepthMask(false);
6747 GL_DepthRange(0, 1);
6748 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6749 // R_Mesh_ResetTextureState();
6751 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6752 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6753 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6754 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6755 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6756 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6757 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6758 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6759 R_FillColors(color4f, 8, cr, cg, cb, ca);
6760 if (r_refdef.fogenabled)
6762 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6764 f1 = RSurf_FogVertex(v);
6766 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6767 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6768 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6771 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6772 R_Mesh_ResetTextureState();
6773 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6774 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6777 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6781 prvm_edict_t *edict;
6782 prvm_prog_t *prog_save = prog;
6784 // this function draws bounding boxes of server entities
6788 GL_CullFace(GL_NONE);
6789 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6793 for (i = 0;i < numsurfaces;i++)
6795 edict = PRVM_EDICT_NUM(surfacelist[i]);
6796 switch ((int)edict->fields.server->solid)
6798 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6799 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6800 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6801 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6802 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6803 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6805 color[3] *= r_showbboxes.value;
6806 color[3] = bound(0, color[3], 1);
6807 GL_DepthTest(!r_showdisabledepthtest.integer);
6808 GL_CullFace(r_refdef.view.cullface_front);
6809 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6815 static void R_DrawEntityBBoxes(void)
6818 prvm_edict_t *edict;
6820 prvm_prog_t *prog_save = prog;
6822 // this function draws bounding boxes of server entities
6828 for (i = 0;i < prog->num_edicts;i++)
6830 edict = PRVM_EDICT_NUM(i);
6831 if (edict->priv.server->free)
6833 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6834 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6836 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6838 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6839 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6845 static const int nomodelelement3i[24] =
6857 static const unsigned short nomodelelement3s[24] =
6869 static const float nomodelvertex3f[6*3] =
6879 static const float nomodelcolor4f[6*4] =
6881 0.0f, 0.0f, 0.5f, 1.0f,
6882 0.0f, 0.0f, 0.5f, 1.0f,
6883 0.0f, 0.5f, 0.0f, 1.0f,
6884 0.0f, 0.5f, 0.0f, 1.0f,
6885 0.5f, 0.0f, 0.0f, 1.0f,
6886 0.5f, 0.0f, 0.0f, 1.0f
6889 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6895 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);
6897 // this is only called once per entity so numsurfaces is always 1, and
6898 // surfacelist is always {0}, so this code does not handle batches
6900 if (rsurface.ent_flags & RENDER_ADDITIVE)
6902 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6903 GL_DepthMask(false);
6905 else if (rsurface.colormod[3] < 1)
6907 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6908 GL_DepthMask(false);
6912 GL_BlendFunc(GL_ONE, GL_ZERO);
6915 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6916 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6917 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6918 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6919 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6920 for (i = 0, c = color4f;i < 6;i++, c += 4)
6922 c[0] *= rsurface.colormod[0];
6923 c[1] *= rsurface.colormod[1];
6924 c[2] *= rsurface.colormod[2];
6925 c[3] *= rsurface.colormod[3];
6927 if (r_refdef.fogenabled)
6929 for (i = 0, c = color4f;i < 6;i++, c += 4)
6931 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6933 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6934 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6935 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6938 // R_Mesh_ResetTextureState();
6939 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6940 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6941 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6944 void R_DrawNoModel(entity_render_t *ent)
6947 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6948 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6949 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6951 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6954 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6956 vec3_t right1, right2, diff, normal;
6958 VectorSubtract (org2, org1, normal);
6960 // calculate 'right' vector for start
6961 VectorSubtract (r_refdef.view.origin, org1, diff);
6962 CrossProduct (normal, diff, right1);
6963 VectorNormalize (right1);
6965 // calculate 'right' vector for end
6966 VectorSubtract (r_refdef.view.origin, org2, diff);
6967 CrossProduct (normal, diff, right2);
6968 VectorNormalize (right2);
6970 vert[ 0] = org1[0] + width * right1[0];
6971 vert[ 1] = org1[1] + width * right1[1];
6972 vert[ 2] = org1[2] + width * right1[2];
6973 vert[ 3] = org1[0] - width * right1[0];
6974 vert[ 4] = org1[1] - width * right1[1];
6975 vert[ 5] = org1[2] - width * right1[2];
6976 vert[ 6] = org2[0] - width * right2[0];
6977 vert[ 7] = org2[1] - width * right2[1];
6978 vert[ 8] = org2[2] - width * right2[2];
6979 vert[ 9] = org2[0] + width * right2[0];
6980 vert[10] = org2[1] + width * right2[1];
6981 vert[11] = org2[2] + width * right2[2];
6984 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)
6986 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6987 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6988 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6989 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6990 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
6991 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
6992 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
6993 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
6994 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
6995 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
6996 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
6997 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7000 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7005 VectorSet(v, x, y, z);
7006 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7007 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7009 if (i == mesh->numvertices)
7011 if (mesh->numvertices < mesh->maxvertices)
7013 VectorCopy(v, vertex3f);
7014 mesh->numvertices++;
7016 return mesh->numvertices;
7022 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7026 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7027 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7028 e = mesh->element3i + mesh->numtriangles * 3;
7029 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7031 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7032 if (mesh->numtriangles < mesh->maxtriangles)
7037 mesh->numtriangles++;
7039 element[1] = element[2];
7043 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7047 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7048 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7049 e = mesh->element3i + mesh->numtriangles * 3;
7050 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7052 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7053 if (mesh->numtriangles < mesh->maxtriangles)
7058 mesh->numtriangles++;
7060 element[1] = element[2];
7064 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7065 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7067 int planenum, planenum2;
7070 mplane_t *plane, *plane2;
7072 double temppoints[2][256*3];
7073 // figure out how large a bounding box we need to properly compute this brush
7075 for (w = 0;w < numplanes;w++)
7076 maxdist = max(maxdist, fabs(planes[w].dist));
7077 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7078 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7079 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7083 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7084 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7086 if (planenum2 == planenum)
7088 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);
7091 if (tempnumpoints < 3)
7093 // generate elements forming a triangle fan for this polygon
7094 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7098 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)
7100 texturelayer_t *layer;
7101 layer = t->currentlayers + t->currentnumlayers++;
7103 layer->depthmask = depthmask;
7104 layer->blendfunc1 = blendfunc1;
7105 layer->blendfunc2 = blendfunc2;
7106 layer->texture = texture;
7107 layer->texmatrix = *matrix;
7108 layer->color[0] = r;
7109 layer->color[1] = g;
7110 layer->color[2] = b;
7111 layer->color[3] = a;
7114 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7116 if(parms[0] == 0 && parms[1] == 0)
7118 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7119 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7124 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7127 index = parms[2] + r_refdef.scene.time * parms[3];
7128 index -= floor(index);
7129 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7132 case Q3WAVEFUNC_NONE:
7133 case Q3WAVEFUNC_NOISE:
7134 case Q3WAVEFUNC_COUNT:
7137 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7138 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7139 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7140 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7141 case Q3WAVEFUNC_TRIANGLE:
7143 f = index - floor(index);
7154 f = parms[0] + parms[1] * f;
7155 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7156 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7160 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7165 matrix4x4_t matrix, temp;
7166 switch(tcmod->tcmod)
7170 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7171 matrix = r_waterscrollmatrix;
7173 matrix = identitymatrix;
7175 case Q3TCMOD_ENTITYTRANSLATE:
7176 // this is used in Q3 to allow the gamecode to control texcoord
7177 // scrolling on the entity, which is not supported in darkplaces yet.
7178 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7180 case Q3TCMOD_ROTATE:
7181 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7182 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7183 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7186 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7188 case Q3TCMOD_SCROLL:
7189 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7191 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7192 w = (int) tcmod->parms[0];
7193 h = (int) tcmod->parms[1];
7194 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7196 idx = (int) floor(f * w * h);
7197 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7199 case Q3TCMOD_STRETCH:
7200 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7201 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7203 case Q3TCMOD_TRANSFORM:
7204 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7205 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7206 VectorSet(tcmat + 6, 0 , 0 , 1);
7207 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7208 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7210 case Q3TCMOD_TURBULENT:
7211 // this is handled in the RSurf_PrepareVertices function
7212 matrix = identitymatrix;
7216 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7219 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7221 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7222 char name[MAX_QPATH];
7223 skinframe_t *skinframe;
7224 unsigned char pixels[296*194];
7225 strlcpy(cache->name, skinname, sizeof(cache->name));
7226 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7227 if (developer_loading.integer)
7228 Con_Printf("loading %s\n", name);
7229 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7230 if (!skinframe || !skinframe->base)
7233 fs_offset_t filesize;
7235 f = FS_LoadFile(name, tempmempool, true, &filesize);
7238 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7239 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7243 cache->skinframe = skinframe;
7246 texture_t *R_GetCurrentTexture(texture_t *t)
7249 const entity_render_t *ent = rsurface.entity;
7250 dp_model_t *model = ent->model;
7251 q3shaderinfo_layer_tcmod_t *tcmod;
7253 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7254 return t->currentframe;
7255 t->update_lastrenderframe = r_textureframe;
7256 t->update_lastrenderentity = (void *)ent;
7258 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7259 t->camera_entity = ent->entitynumber;
7261 t->camera_entity = 0;
7263 // switch to an alternate material if this is a q1bsp animated material
7265 texture_t *texture = t;
7266 int s = rsurface.ent_skinnum;
7267 if ((unsigned int)s >= (unsigned int)model->numskins)
7269 if (model->skinscenes)
7271 if (model->skinscenes[s].framecount > 1)
7272 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7274 s = model->skinscenes[s].firstframe;
7277 t = t + s * model->num_surfaces;
7280 // use an alternate animation if the entity's frame is not 0,
7281 // and only if the texture has an alternate animation
7282 if (rsurface.ent_alttextures && t->anim_total[1])
7283 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7285 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7287 texture->currentframe = t;
7290 // update currentskinframe to be a qw skin or animation frame
7291 if (rsurface.ent_qwskin >= 0)
7293 i = rsurface.ent_qwskin;
7294 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7296 r_qwskincache_size = cl.maxclients;
7298 Mem_Free(r_qwskincache);
7299 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7301 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7302 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7303 t->currentskinframe = r_qwskincache[i].skinframe;
7304 if (t->currentskinframe == NULL)
7305 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7307 else if (t->numskinframes >= 2)
7308 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7309 if (t->backgroundnumskinframes >= 2)
7310 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7312 t->currentmaterialflags = t->basematerialflags;
7313 t->currentalpha = rsurface.colormod[3];
7314 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7315 t->currentalpha *= r_wateralpha.value;
7316 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7317 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7318 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7319 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7320 if (!(rsurface.ent_flags & RENDER_LIGHT))
7321 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7322 else if (FAKELIGHT_ENABLED)
7324 // no modellight if using fakelight for the map
7326 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7328 // pick a model lighting mode
7329 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7330 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7332 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7334 if (rsurface.ent_flags & RENDER_ADDITIVE)
7335 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7336 else if (t->currentalpha < 1)
7337 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7338 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7339 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7340 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7341 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7342 if (t->backgroundnumskinframes)
7343 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7344 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7346 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7347 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7350 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7351 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7352 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7354 // there is no tcmod
7355 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7357 t->currenttexmatrix = r_waterscrollmatrix;
7358 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7360 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7362 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7363 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7366 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7367 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7368 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7369 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7371 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7372 if (t->currentskinframe->qpixels)
7373 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7374 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7375 if (!t->basetexture)
7376 t->basetexture = r_texture_notexture;
7377 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7378 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7379 t->nmaptexture = t->currentskinframe->nmap;
7380 if (!t->nmaptexture)
7381 t->nmaptexture = r_texture_blanknormalmap;
7382 t->glosstexture = r_texture_black;
7383 t->glowtexture = t->currentskinframe->glow;
7384 t->fogtexture = t->currentskinframe->fog;
7385 t->reflectmasktexture = t->currentskinframe->reflect;
7386 if (t->backgroundnumskinframes)
7388 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7389 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7390 t->backgroundglosstexture = r_texture_black;
7391 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7392 if (!t->backgroundnmaptexture)
7393 t->backgroundnmaptexture = r_texture_blanknormalmap;
7397 t->backgroundbasetexture = r_texture_white;
7398 t->backgroundnmaptexture = r_texture_blanknormalmap;
7399 t->backgroundglosstexture = r_texture_black;
7400 t->backgroundglowtexture = NULL;
7402 t->specularpower = r_shadow_glossexponent.value;
7403 // TODO: store reference values for these in the texture?
7404 t->specularscale = 0;
7405 if (r_shadow_gloss.integer > 0)
7407 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7409 if (r_shadow_glossintensity.value > 0)
7411 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7412 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7413 t->specularscale = r_shadow_glossintensity.value;
7416 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7418 t->glosstexture = r_texture_white;
7419 t->backgroundglosstexture = r_texture_white;
7420 t->specularscale = r_shadow_gloss2intensity.value;
7421 t->specularpower = r_shadow_gloss2exponent.value;
7424 t->specularscale *= t->specularscalemod;
7425 t->specularpower *= t->specularpowermod;
7427 // lightmaps mode looks bad with dlights using actual texturing, so turn
7428 // off the colormap and glossmap, but leave the normalmap on as it still
7429 // accurately represents the shading involved
7430 if (gl_lightmaps.integer)
7432 t->basetexture = r_texture_grey128;
7433 t->pantstexture = r_texture_black;
7434 t->shirttexture = r_texture_black;
7435 t->nmaptexture = r_texture_blanknormalmap;
7436 t->glosstexture = r_texture_black;
7437 t->glowtexture = NULL;
7438 t->fogtexture = NULL;
7439 t->reflectmasktexture = NULL;
7440 t->backgroundbasetexture = NULL;
7441 t->backgroundnmaptexture = r_texture_blanknormalmap;
7442 t->backgroundglosstexture = r_texture_black;
7443 t->backgroundglowtexture = NULL;
7444 t->specularscale = 0;
7445 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7448 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7449 VectorClear(t->dlightcolor);
7450 t->currentnumlayers = 0;
7451 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7453 int blendfunc1, blendfunc2;
7455 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7457 blendfunc1 = GL_SRC_ALPHA;
7458 blendfunc2 = GL_ONE;
7460 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7462 blendfunc1 = GL_SRC_ALPHA;
7463 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7465 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7467 blendfunc1 = t->customblendfunc[0];
7468 blendfunc2 = t->customblendfunc[1];
7472 blendfunc1 = GL_ONE;
7473 blendfunc2 = GL_ZERO;
7475 // don't colormod evilblend textures
7476 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7477 VectorSet(t->lightmapcolor, 1, 1, 1);
7478 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7479 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7481 // fullbright is not affected by r_refdef.lightmapintensity
7482 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]);
7483 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7484 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]);
7485 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7486 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]);
7490 vec3_t ambientcolor;
7492 // set the color tint used for lights affecting this surface
7493 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7495 // q3bsp has no lightmap updates, so the lightstylevalue that
7496 // would normally be baked into the lightmap must be
7497 // applied to the color
7498 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7499 if (model->type == mod_brushq3)
7500 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7501 colorscale *= r_refdef.lightmapintensity;
7502 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7503 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7504 // basic lit geometry
7505 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]);
7506 // add pants/shirt if needed
7507 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7508 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]);
7509 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7510 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]);
7511 // now add ambient passes if needed
7512 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7514 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]);
7515 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7516 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]);
7517 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7518 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]);
7521 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7522 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]);
7523 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7525 // if this is opaque use alpha blend which will darken the earlier
7528 // if this is an alpha blended material, all the earlier passes
7529 // were darkened by fog already, so we only need to add the fog
7530 // color ontop through the fog mask texture
7532 // if this is an additive blended material, all the earlier passes
7533 // were darkened by fog already, and we should not add fog color
7534 // (because the background was not darkened, there is no fog color
7535 // that was lost behind it).
7536 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]);
7540 return t->currentframe;
7543 rsurfacestate_t rsurface;
7545 void RSurf_ActiveWorldEntity(void)
7547 dp_model_t *model = r_refdef.scene.worldmodel;
7548 //if (rsurface.entity == r_refdef.scene.worldentity)
7550 rsurface.entity = r_refdef.scene.worldentity;
7551 rsurface.skeleton = NULL;
7552 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7553 rsurface.ent_skinnum = 0;
7554 rsurface.ent_qwskin = -1;
7555 rsurface.ent_shadertime = 0;
7556 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7557 rsurface.matrix = identitymatrix;
7558 rsurface.inversematrix = identitymatrix;
7559 rsurface.matrixscale = 1;
7560 rsurface.inversematrixscale = 1;
7561 R_EntityMatrix(&identitymatrix);
7562 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7563 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7564 rsurface.fograngerecip = r_refdef.fograngerecip;
7565 rsurface.fogheightfade = r_refdef.fogheightfade;
7566 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7567 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7568 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7569 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7570 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7571 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7572 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7573 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7574 rsurface.colormod[3] = 1;
7575 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);
7576 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7577 rsurface.frameblend[0].lerp = 1;
7578 rsurface.ent_alttextures = false;
7579 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7580 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7581 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7582 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7583 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7584 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7585 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7586 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7587 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7588 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7589 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7590 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7591 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7592 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7593 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7594 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7595 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7596 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7597 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7598 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7599 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7600 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7601 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7602 rsurface.modelelement3i = model->surfmesh.data_element3i;
7603 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7604 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7605 rsurface.modelelement3s = model->surfmesh.data_element3s;
7606 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7607 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7608 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7609 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7610 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7611 rsurface.modelsurfaces = model->data_surfaces;
7612 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7613 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7614 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7615 rsurface.modelgeneratedvertex = false;
7616 rsurface.batchgeneratedvertex = false;
7617 rsurface.batchfirstvertex = 0;
7618 rsurface.batchnumvertices = 0;
7619 rsurface.batchfirsttriangle = 0;
7620 rsurface.batchnumtriangles = 0;
7621 rsurface.batchvertex3f = NULL;
7622 rsurface.batchvertex3f_vertexbuffer = NULL;
7623 rsurface.batchvertex3f_bufferoffset = 0;
7624 rsurface.batchsvector3f = NULL;
7625 rsurface.batchsvector3f_vertexbuffer = NULL;
7626 rsurface.batchsvector3f_bufferoffset = 0;
7627 rsurface.batchtvector3f = NULL;
7628 rsurface.batchtvector3f_vertexbuffer = NULL;
7629 rsurface.batchtvector3f_bufferoffset = 0;
7630 rsurface.batchnormal3f = NULL;
7631 rsurface.batchnormal3f_vertexbuffer = NULL;
7632 rsurface.batchnormal3f_bufferoffset = 0;
7633 rsurface.batchlightmapcolor4f = NULL;
7634 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7635 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7636 rsurface.batchtexcoordtexture2f = NULL;
7637 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7638 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7639 rsurface.batchtexcoordlightmap2f = NULL;
7640 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7641 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7642 rsurface.batchvertexmesh = NULL;
7643 rsurface.batchvertexmeshbuffer = NULL;
7644 rsurface.batchvertex3fbuffer = NULL;
7645 rsurface.batchelement3i = NULL;
7646 rsurface.batchelement3i_indexbuffer = NULL;
7647 rsurface.batchelement3i_bufferoffset = 0;
7648 rsurface.batchelement3s = NULL;
7649 rsurface.batchelement3s_indexbuffer = NULL;
7650 rsurface.batchelement3s_bufferoffset = 0;
7651 rsurface.passcolor4f = NULL;
7652 rsurface.passcolor4f_vertexbuffer = NULL;
7653 rsurface.passcolor4f_bufferoffset = 0;
7656 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7658 dp_model_t *model = ent->model;
7659 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7661 rsurface.entity = (entity_render_t *)ent;
7662 rsurface.skeleton = ent->skeleton;
7663 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7664 rsurface.ent_skinnum = ent->skinnum;
7665 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;
7666 rsurface.ent_shadertime = ent->shadertime;
7667 rsurface.ent_flags = ent->flags;
7668 rsurface.matrix = ent->matrix;
7669 rsurface.inversematrix = ent->inversematrix;
7670 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7671 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7672 R_EntityMatrix(&rsurface.matrix);
7673 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7674 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7675 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7676 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7677 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7678 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7679 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7680 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7681 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7682 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7683 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7684 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7685 rsurface.colormod[3] = ent->alpha;
7686 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7687 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7688 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7689 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7690 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7691 if (ent->model->brush.submodel && !prepass)
7693 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7694 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7696 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7698 if (ent->animcache_vertex3f)
7700 rsurface.modelvertex3f = ent->animcache_vertex3f;
7701 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7702 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7703 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7704 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7705 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7706 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7708 else if (wanttangents)
7710 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7711 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7712 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7713 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7714 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7715 rsurface.modelvertexmesh = NULL;
7716 rsurface.modelvertexmeshbuffer = NULL;
7717 rsurface.modelvertex3fbuffer = NULL;
7719 else if (wantnormals)
7721 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7722 rsurface.modelsvector3f = NULL;
7723 rsurface.modeltvector3f = NULL;
7724 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7725 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7726 rsurface.modelvertexmesh = NULL;
7727 rsurface.modelvertexmeshbuffer = NULL;
7728 rsurface.modelvertex3fbuffer = NULL;
7732 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7733 rsurface.modelsvector3f = NULL;
7734 rsurface.modeltvector3f = NULL;
7735 rsurface.modelnormal3f = NULL;
7736 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7737 rsurface.modelvertexmesh = NULL;
7738 rsurface.modelvertexmeshbuffer = NULL;
7739 rsurface.modelvertex3fbuffer = NULL;
7741 rsurface.modelvertex3f_vertexbuffer = 0;
7742 rsurface.modelvertex3f_bufferoffset = 0;
7743 rsurface.modelsvector3f_vertexbuffer = 0;
7744 rsurface.modelsvector3f_bufferoffset = 0;
7745 rsurface.modeltvector3f_vertexbuffer = 0;
7746 rsurface.modeltvector3f_bufferoffset = 0;
7747 rsurface.modelnormal3f_vertexbuffer = 0;
7748 rsurface.modelnormal3f_bufferoffset = 0;
7749 rsurface.modelgeneratedvertex = true;
7753 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7754 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7755 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7756 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7757 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7758 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7759 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7760 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7761 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7762 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7763 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7764 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7765 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7766 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7767 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7768 rsurface.modelgeneratedvertex = false;
7770 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7771 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7772 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7773 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7774 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7775 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7776 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7777 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7778 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7779 rsurface.modelelement3i = model->surfmesh.data_element3i;
7780 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7781 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7782 rsurface.modelelement3s = model->surfmesh.data_element3s;
7783 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7784 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7785 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7786 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7787 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7788 rsurface.modelsurfaces = model->data_surfaces;
7789 rsurface.batchgeneratedvertex = false;
7790 rsurface.batchfirstvertex = 0;
7791 rsurface.batchnumvertices = 0;
7792 rsurface.batchfirsttriangle = 0;
7793 rsurface.batchnumtriangles = 0;
7794 rsurface.batchvertex3f = NULL;
7795 rsurface.batchvertex3f_vertexbuffer = NULL;
7796 rsurface.batchvertex3f_bufferoffset = 0;
7797 rsurface.batchsvector3f = NULL;
7798 rsurface.batchsvector3f_vertexbuffer = NULL;
7799 rsurface.batchsvector3f_bufferoffset = 0;
7800 rsurface.batchtvector3f = NULL;
7801 rsurface.batchtvector3f_vertexbuffer = NULL;
7802 rsurface.batchtvector3f_bufferoffset = 0;
7803 rsurface.batchnormal3f = NULL;
7804 rsurface.batchnormal3f_vertexbuffer = NULL;
7805 rsurface.batchnormal3f_bufferoffset = 0;
7806 rsurface.batchlightmapcolor4f = NULL;
7807 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7808 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7809 rsurface.batchtexcoordtexture2f = NULL;
7810 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7811 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7812 rsurface.batchtexcoordlightmap2f = NULL;
7813 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7814 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7815 rsurface.batchvertexmesh = NULL;
7816 rsurface.batchvertexmeshbuffer = NULL;
7817 rsurface.batchvertex3fbuffer = NULL;
7818 rsurface.batchelement3i = NULL;
7819 rsurface.batchelement3i_indexbuffer = NULL;
7820 rsurface.batchelement3i_bufferoffset = 0;
7821 rsurface.batchelement3s = NULL;
7822 rsurface.batchelement3s_indexbuffer = NULL;
7823 rsurface.batchelement3s_bufferoffset = 0;
7824 rsurface.passcolor4f = NULL;
7825 rsurface.passcolor4f_vertexbuffer = NULL;
7826 rsurface.passcolor4f_bufferoffset = 0;
7829 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)
7831 rsurface.entity = r_refdef.scene.worldentity;
7832 rsurface.skeleton = NULL;
7833 rsurface.ent_skinnum = 0;
7834 rsurface.ent_qwskin = -1;
7835 rsurface.ent_shadertime = shadertime;
7836 rsurface.ent_flags = entflags;
7837 rsurface.modelnumvertices = numvertices;
7838 rsurface.modelnumtriangles = numtriangles;
7839 rsurface.matrix = *matrix;
7840 rsurface.inversematrix = *inversematrix;
7841 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7842 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7843 R_EntityMatrix(&rsurface.matrix);
7844 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7845 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7846 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7847 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7848 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7849 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7850 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7851 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7852 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7853 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7854 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7855 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7856 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);
7857 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7858 rsurface.frameblend[0].lerp = 1;
7859 rsurface.ent_alttextures = false;
7860 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7861 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7864 rsurface.modelvertex3f = (float *)vertex3f;
7865 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7866 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7867 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7869 else if (wantnormals)
7871 rsurface.modelvertex3f = (float *)vertex3f;
7872 rsurface.modelsvector3f = NULL;
7873 rsurface.modeltvector3f = NULL;
7874 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7878 rsurface.modelvertex3f = (float *)vertex3f;
7879 rsurface.modelsvector3f = NULL;
7880 rsurface.modeltvector3f = NULL;
7881 rsurface.modelnormal3f = NULL;
7883 rsurface.modelvertexmesh = NULL;
7884 rsurface.modelvertexmeshbuffer = NULL;
7885 rsurface.modelvertex3fbuffer = NULL;
7886 rsurface.modelvertex3f_vertexbuffer = 0;
7887 rsurface.modelvertex3f_bufferoffset = 0;
7888 rsurface.modelsvector3f_vertexbuffer = 0;
7889 rsurface.modelsvector3f_bufferoffset = 0;
7890 rsurface.modeltvector3f_vertexbuffer = 0;
7891 rsurface.modeltvector3f_bufferoffset = 0;
7892 rsurface.modelnormal3f_vertexbuffer = 0;
7893 rsurface.modelnormal3f_bufferoffset = 0;
7894 rsurface.modelgeneratedvertex = true;
7895 rsurface.modellightmapcolor4f = (float *)color4f;
7896 rsurface.modellightmapcolor4f_vertexbuffer = 0;
7897 rsurface.modellightmapcolor4f_bufferoffset = 0;
7898 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
7899 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7900 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7901 rsurface.modeltexcoordlightmap2f = NULL;
7902 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7903 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7904 rsurface.modelelement3i = (int *)element3i;
7905 rsurface.modelelement3i_indexbuffer = NULL;
7906 rsurface.modelelement3i_bufferoffset = 0;
7907 rsurface.modelelement3s = (unsigned short *)element3s;
7908 rsurface.modelelement3s_indexbuffer = NULL;
7909 rsurface.modelelement3s_bufferoffset = 0;
7910 rsurface.modellightmapoffsets = NULL;
7911 rsurface.modelsurfaces = NULL;
7912 rsurface.batchgeneratedvertex = false;
7913 rsurface.batchfirstvertex = 0;
7914 rsurface.batchnumvertices = 0;
7915 rsurface.batchfirsttriangle = 0;
7916 rsurface.batchnumtriangles = 0;
7917 rsurface.batchvertex3f = NULL;
7918 rsurface.batchvertex3f_vertexbuffer = NULL;
7919 rsurface.batchvertex3f_bufferoffset = 0;
7920 rsurface.batchsvector3f = NULL;
7921 rsurface.batchsvector3f_vertexbuffer = NULL;
7922 rsurface.batchsvector3f_bufferoffset = 0;
7923 rsurface.batchtvector3f = NULL;
7924 rsurface.batchtvector3f_vertexbuffer = NULL;
7925 rsurface.batchtvector3f_bufferoffset = 0;
7926 rsurface.batchnormal3f = NULL;
7927 rsurface.batchnormal3f_vertexbuffer = NULL;
7928 rsurface.batchnormal3f_bufferoffset = 0;
7929 rsurface.batchlightmapcolor4f = NULL;
7930 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7931 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7932 rsurface.batchtexcoordtexture2f = NULL;
7933 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7934 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7935 rsurface.batchtexcoordlightmap2f = NULL;
7936 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7937 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7938 rsurface.batchvertexmesh = NULL;
7939 rsurface.batchvertexmeshbuffer = NULL;
7940 rsurface.batchvertex3fbuffer = NULL;
7941 rsurface.batchelement3i = NULL;
7942 rsurface.batchelement3i_indexbuffer = NULL;
7943 rsurface.batchelement3i_bufferoffset = 0;
7944 rsurface.batchelement3s = NULL;
7945 rsurface.batchelement3s_indexbuffer = NULL;
7946 rsurface.batchelement3s_bufferoffset = 0;
7947 rsurface.passcolor4f = NULL;
7948 rsurface.passcolor4f_vertexbuffer = NULL;
7949 rsurface.passcolor4f_bufferoffset = 0;
7951 if (rsurface.modelnumvertices && rsurface.modelelement3i)
7953 if ((wantnormals || wanttangents) && !normal3f)
7955 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7956 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7958 if (wanttangents && !svector3f)
7960 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7961 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7962 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7967 float RSurf_FogPoint(const float *v)
7969 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7970 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7971 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7972 float FogHeightFade = r_refdef.fogheightfade;
7974 unsigned int fogmasktableindex;
7975 if (r_refdef.fogplaneviewabove)
7976 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7978 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7979 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7980 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7983 float RSurf_FogVertex(const float *v)
7985 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7986 float FogPlaneViewDist = rsurface.fogplaneviewdist;
7987 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7988 float FogHeightFade = rsurface.fogheightfade;
7990 unsigned int fogmasktableindex;
7991 if (r_refdef.fogplaneviewabove)
7992 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7994 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7995 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
7996 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7999 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8002 for (i = 0;i < numelements;i++)
8003 outelement3i[i] = inelement3i[i] + adjust;
8006 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8007 extern cvar_t gl_vbo;
8008 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8016 int surfacefirsttriangle;
8017 int surfacenumtriangles;
8018 int surfacefirstvertex;
8019 int surfaceendvertex;
8020 int surfacenumvertices;
8021 int batchnumvertices;
8022 int batchnumtriangles;
8026 qboolean dynamicvertex;
8030 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8032 q3shaderinfo_deform_t *deform;
8033 const msurface_t *surface, *firstsurface;
8034 r_vertexmesh_t *vertexmesh;
8035 if (!texturenumsurfaces)
8037 // find vertex range of this surface batch
8039 firstsurface = texturesurfacelist[0];
8040 firsttriangle = firstsurface->num_firsttriangle;
8041 batchnumvertices = 0;
8042 batchnumtriangles = 0;
8043 firstvertex = endvertex = firstsurface->num_firstvertex;
8044 for (i = 0;i < texturenumsurfaces;i++)
8046 surface = texturesurfacelist[i];
8047 if (surface != firstsurface + i)
8049 surfacefirstvertex = surface->num_firstvertex;
8050 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8051 surfacenumvertices = surface->num_vertices;
8052 surfacenumtriangles = surface->num_triangles;
8053 if (firstvertex > surfacefirstvertex)
8054 firstvertex = surfacefirstvertex;
8055 if (endvertex < surfaceendvertex)
8056 endvertex = surfaceendvertex;
8057 batchnumvertices += surfacenumvertices;
8058 batchnumtriangles += surfacenumtriangles;
8061 // we now know the vertex range used, and if there are any gaps in it
8062 rsurface.batchfirstvertex = firstvertex;
8063 rsurface.batchnumvertices = endvertex - firstvertex;
8064 rsurface.batchfirsttriangle = firsttriangle;
8065 rsurface.batchnumtriangles = batchnumtriangles;
8067 // this variable holds flags for which properties have been updated that
8068 // may require regenerating vertexmesh array...
8071 // check if any dynamic vertex processing must occur
8072 dynamicvertex = false;
8074 // if there is a chance of animated vertex colors, it's a dynamic batch
8075 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8077 dynamicvertex = true;
8078 batchneed |= BATCHNEED_NOGAPS;
8079 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8082 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8084 switch (deform->deform)
8087 case Q3DEFORM_PROJECTIONSHADOW:
8088 case Q3DEFORM_TEXT0:
8089 case Q3DEFORM_TEXT1:
8090 case Q3DEFORM_TEXT2:
8091 case Q3DEFORM_TEXT3:
8092 case Q3DEFORM_TEXT4:
8093 case Q3DEFORM_TEXT5:
8094 case Q3DEFORM_TEXT6:
8095 case Q3DEFORM_TEXT7:
8098 case Q3DEFORM_AUTOSPRITE:
8099 dynamicvertex = true;
8100 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8101 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8103 case Q3DEFORM_AUTOSPRITE2:
8104 dynamicvertex = true;
8105 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8106 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8108 case Q3DEFORM_NORMAL:
8109 dynamicvertex = true;
8110 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8111 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8114 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8115 break; // if wavefunc is a nop, ignore this transform
8116 dynamicvertex = true;
8117 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8118 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8120 case Q3DEFORM_BULGE:
8121 dynamicvertex = true;
8122 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8123 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8126 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8127 break; // if wavefunc is a nop, ignore this transform
8128 dynamicvertex = true;
8129 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8130 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8134 switch(rsurface.texture->tcgen.tcgen)
8137 case Q3TCGEN_TEXTURE:
8139 case Q3TCGEN_LIGHTMAP:
8140 dynamicvertex = true;
8141 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8142 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8144 case Q3TCGEN_VECTOR:
8145 dynamicvertex = true;
8146 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8147 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8149 case Q3TCGEN_ENVIRONMENT:
8150 dynamicvertex = true;
8151 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8152 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8155 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8157 dynamicvertex = true;
8158 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8159 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8162 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8164 dynamicvertex = true;
8165 batchneed |= BATCHNEED_NOGAPS;
8166 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8169 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8171 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8172 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8173 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8174 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8175 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8176 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8177 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8180 // when the model data has no vertex buffer (dynamic mesh), we need to
8182 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8183 batchneed |= BATCHNEED_NOGAPS;
8185 // if needsupdate, we have to do a dynamic vertex batch for sure
8186 if (needsupdate & batchneed)
8187 dynamicvertex = true;
8189 // see if we need to build vertexmesh from arrays
8190 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8191 dynamicvertex = true;
8193 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8194 // also some drivers strongly dislike firstvertex
8195 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8196 dynamicvertex = true;
8198 rsurface.batchvertex3f = rsurface.modelvertex3f;
8199 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8200 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8201 rsurface.batchsvector3f = rsurface.modelsvector3f;
8202 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8203 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8204 rsurface.batchtvector3f = rsurface.modeltvector3f;
8205 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8206 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8207 rsurface.batchnormal3f = rsurface.modelnormal3f;
8208 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8209 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8210 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8211 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8212 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8213 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8214 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8215 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8216 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8217 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8218 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8219 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8220 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8221 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8222 rsurface.batchelement3i = rsurface.modelelement3i;
8223 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8224 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8225 rsurface.batchelement3s = rsurface.modelelement3s;
8226 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8227 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8229 // if any dynamic vertex processing has to occur in software, we copy the
8230 // entire surface list together before processing to rebase the vertices
8231 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8233 // if any gaps exist and we do not have a static vertex buffer, we have to
8234 // copy the surface list together to avoid wasting upload bandwidth on the
8235 // vertices in the gaps.
8237 // if gaps exist and we have a static vertex buffer, we still have to
8238 // combine the index buffer ranges into one dynamic index buffer.
8240 // in all cases we end up with data that can be drawn in one call.
8244 // static vertex data, just set pointers...
8245 rsurface.batchgeneratedvertex = false;
8246 // if there are gaps, we want to build a combined index buffer,
8247 // otherwise use the original static buffer with an appropriate offset
8250 // build a new triangle elements array for this batch
8251 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8252 rsurface.batchfirsttriangle = 0;
8254 for (i = 0;i < texturenumsurfaces;i++)
8256 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8257 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8258 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8259 numtriangles += surfacenumtriangles;
8261 rsurface.batchelement3i_indexbuffer = NULL;
8262 rsurface.batchelement3i_bufferoffset = 0;
8263 rsurface.batchelement3s = NULL;
8264 rsurface.batchelement3s_indexbuffer = NULL;
8265 rsurface.batchelement3s_bufferoffset = 0;
8266 if (endvertex <= 65536)
8268 // make a 16bit (unsigned short) index array if possible
8269 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8270 for (i = 0;i < numtriangles*3;i++)
8271 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8277 // something needs software processing, do it for real...
8278 // we only directly handle separate array data in this case and then
8279 // generate interleaved data if needed...
8280 rsurface.batchgeneratedvertex = true;
8282 // now copy the vertex data into a combined array and make an index array
8283 // (this is what Quake3 does all the time)
8284 //if (gaps || rsurface.batchfirstvertex)
8286 rsurface.batchvertex3fbuffer = NULL;
8287 rsurface.batchvertexmesh = NULL;
8288 rsurface.batchvertexmeshbuffer = NULL;
8289 rsurface.batchvertex3f = NULL;
8290 rsurface.batchvertex3f_vertexbuffer = NULL;
8291 rsurface.batchvertex3f_bufferoffset = 0;
8292 rsurface.batchsvector3f = NULL;
8293 rsurface.batchsvector3f_vertexbuffer = NULL;
8294 rsurface.batchsvector3f_bufferoffset = 0;
8295 rsurface.batchtvector3f = NULL;
8296 rsurface.batchtvector3f_vertexbuffer = NULL;
8297 rsurface.batchtvector3f_bufferoffset = 0;
8298 rsurface.batchnormal3f = NULL;
8299 rsurface.batchnormal3f_vertexbuffer = NULL;
8300 rsurface.batchnormal3f_bufferoffset = 0;
8301 rsurface.batchlightmapcolor4f = NULL;
8302 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8303 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8304 rsurface.batchtexcoordtexture2f = NULL;
8305 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8306 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8307 rsurface.batchtexcoordlightmap2f = NULL;
8308 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8309 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8310 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8311 rsurface.batchelement3i_indexbuffer = NULL;
8312 rsurface.batchelement3i_bufferoffset = 0;
8313 rsurface.batchelement3s = NULL;
8314 rsurface.batchelement3s_indexbuffer = NULL;
8315 rsurface.batchelement3s_bufferoffset = 0;
8316 // we'll only be setting up certain arrays as needed
8317 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8318 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8319 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8320 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8321 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8322 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8323 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8325 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8326 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8328 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8329 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8330 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8331 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8332 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8333 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8336 for (i = 0;i < texturenumsurfaces;i++)
8338 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8339 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8340 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8341 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8342 // copy only the data requested
8343 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8344 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8345 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8347 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8348 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8349 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8350 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8351 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8353 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8354 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8356 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8357 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8358 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8359 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8360 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8361 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8363 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8364 numvertices += surfacenumvertices;
8365 numtriangles += surfacenumtriangles;
8368 // generate a 16bit index array as well if possible
8369 // (in general, dynamic batches fit)
8370 if (numvertices <= 65536)
8372 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8373 for (i = 0;i < numtriangles*3;i++)
8374 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8377 // since we've copied everything, the batch now starts at 0
8378 rsurface.batchfirstvertex = 0;
8379 rsurface.batchnumvertices = batchnumvertices;
8380 rsurface.batchfirsttriangle = 0;
8381 rsurface.batchnumtriangles = batchnumtriangles;
8384 // q1bsp surfaces rendered in vertex color mode have to have colors
8385 // calculated based on lightstyles
8386 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8388 // generate color arrays for the surfaces in this list
8393 const unsigned char *lm;
8394 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8395 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8396 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8398 for (i = 0;i < texturenumsurfaces;i++)
8400 surface = texturesurfacelist[i];
8401 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8402 surfacenumvertices = surface->num_vertices;
8403 if (surface->lightmapinfo->samples)
8405 for (j = 0;j < surfacenumvertices;j++)
8407 lm = surface->lightmapinfo->samples + offsets[j];
8408 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8409 VectorScale(lm, scale, c);
8410 if (surface->lightmapinfo->styles[1] != 255)
8412 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8414 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8415 VectorMA(c, scale, lm, c);
8416 if (surface->lightmapinfo->styles[2] != 255)
8419 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8420 VectorMA(c, scale, lm, c);
8421 if (surface->lightmapinfo->styles[3] != 255)
8424 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8425 VectorMA(c, scale, lm, c);
8432 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);
8438 for (j = 0;j < surfacenumvertices;j++)
8440 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8447 // if vertices are deformed (sprite flares and things in maps, possibly
8448 // water waves, bulges and other deformations), modify the copied vertices
8450 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8452 switch (deform->deform)
8455 case Q3DEFORM_PROJECTIONSHADOW:
8456 case Q3DEFORM_TEXT0:
8457 case Q3DEFORM_TEXT1:
8458 case Q3DEFORM_TEXT2:
8459 case Q3DEFORM_TEXT3:
8460 case Q3DEFORM_TEXT4:
8461 case Q3DEFORM_TEXT5:
8462 case Q3DEFORM_TEXT6:
8463 case Q3DEFORM_TEXT7:
8466 case Q3DEFORM_AUTOSPRITE:
8467 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8468 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8469 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8470 VectorNormalize(newforward);
8471 VectorNormalize(newright);
8472 VectorNormalize(newup);
8473 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8474 // rsurface.batchvertex3f_vertexbuffer = NULL;
8475 // rsurface.batchvertex3f_bufferoffset = 0;
8476 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8477 // rsurface.batchsvector3f_vertexbuffer = NULL;
8478 // rsurface.batchsvector3f_bufferoffset = 0;
8479 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8480 // rsurface.batchtvector3f_vertexbuffer = NULL;
8481 // rsurface.batchtvector3f_bufferoffset = 0;
8482 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8483 // rsurface.batchnormal3f_vertexbuffer = NULL;
8484 // rsurface.batchnormal3f_bufferoffset = 0;
8485 // a single autosprite surface can contain multiple sprites...
8486 for (j = 0;j < batchnumvertices - 3;j += 4)
8488 VectorClear(center);
8489 for (i = 0;i < 4;i++)
8490 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8491 VectorScale(center, 0.25f, center);
8492 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8493 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8494 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8495 for (i = 0;i < 4;i++)
8497 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8498 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8501 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8502 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8503 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);
8505 case Q3DEFORM_AUTOSPRITE2:
8506 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8507 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8508 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8509 VectorNormalize(newforward);
8510 VectorNormalize(newright);
8511 VectorNormalize(newup);
8512 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8513 // rsurface.batchvertex3f_vertexbuffer = NULL;
8514 // rsurface.batchvertex3f_bufferoffset = 0;
8516 const float *v1, *v2;
8526 memset(shortest, 0, sizeof(shortest));
8527 // a single autosprite surface can contain multiple sprites...
8528 for (j = 0;j < batchnumvertices - 3;j += 4)
8530 VectorClear(center);
8531 for (i = 0;i < 4;i++)
8532 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8533 VectorScale(center, 0.25f, center);
8534 // find the two shortest edges, then use them to define the
8535 // axis vectors for rotating around the central axis
8536 for (i = 0;i < 6;i++)
8538 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8539 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8540 l = VectorDistance2(v1, v2);
8541 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8543 l += (1.0f / 1024.0f);
8544 if (shortest[0].length2 > l || i == 0)
8546 shortest[1] = shortest[0];
8547 shortest[0].length2 = l;
8548 shortest[0].v1 = v1;
8549 shortest[0].v2 = v2;
8551 else if (shortest[1].length2 > l || i == 1)
8553 shortest[1].length2 = l;
8554 shortest[1].v1 = v1;
8555 shortest[1].v2 = v2;
8558 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8559 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8560 // this calculates the right vector from the shortest edge
8561 // and the up vector from the edge midpoints
8562 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8563 VectorNormalize(right);
8564 VectorSubtract(end, start, up);
8565 VectorNormalize(up);
8566 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8567 VectorSubtract(rsurface.localvieworigin, center, forward);
8568 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8569 VectorNegate(forward, forward);
8570 VectorReflect(forward, 0, up, forward);
8571 VectorNormalize(forward);
8572 CrossProduct(up, forward, newright);
8573 VectorNormalize(newright);
8574 // rotate the quad around the up axis vector, this is made
8575 // especially easy by the fact we know the quad is flat,
8576 // so we only have to subtract the center position and
8577 // measure distance along the right vector, and then
8578 // multiply that by the newright vector and add back the
8580 // we also need to subtract the old position to undo the
8581 // displacement from the center, which we do with a
8582 // DotProduct, the subtraction/addition of center is also
8583 // optimized into DotProducts here
8584 l = DotProduct(right, center);
8585 for (i = 0;i < 4;i++)
8587 v1 = rsurface.batchvertex3f + 3*(j+i);
8588 f = DotProduct(right, v1) - l;
8589 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8593 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8595 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8596 // rsurface.batchnormal3f_vertexbuffer = NULL;
8597 // rsurface.batchnormal3f_bufferoffset = 0;
8598 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8600 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8602 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8603 // rsurface.batchsvector3f_vertexbuffer = NULL;
8604 // rsurface.batchsvector3f_bufferoffset = 0;
8605 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8606 // rsurface.batchtvector3f_vertexbuffer = NULL;
8607 // rsurface.batchtvector3f_bufferoffset = 0;
8608 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);
8611 case Q3DEFORM_NORMAL:
8612 // deform the normals to make reflections wavey
8613 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8614 rsurface.batchnormal3f_vertexbuffer = NULL;
8615 rsurface.batchnormal3f_bufferoffset = 0;
8616 for (j = 0;j < batchnumvertices;j++)
8619 float *normal = rsurface.batchnormal3f + 3*j;
8620 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8621 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8622 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]);
8623 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]);
8624 VectorNormalize(normal);
8626 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8628 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8629 // rsurface.batchsvector3f_vertexbuffer = NULL;
8630 // rsurface.batchsvector3f_bufferoffset = 0;
8631 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8632 // rsurface.batchtvector3f_vertexbuffer = NULL;
8633 // rsurface.batchtvector3f_bufferoffset = 0;
8634 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);
8638 // deform vertex array to make wavey water and flags and such
8639 waveparms[0] = deform->waveparms[0];
8640 waveparms[1] = deform->waveparms[1];
8641 waveparms[2] = deform->waveparms[2];
8642 waveparms[3] = deform->waveparms[3];
8643 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8644 break; // if wavefunc is a nop, don't make a dynamic vertex array
8645 // this is how a divisor of vertex influence on deformation
8646 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8647 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8648 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8649 // rsurface.batchvertex3f_vertexbuffer = NULL;
8650 // rsurface.batchvertex3f_bufferoffset = 0;
8651 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8652 // rsurface.batchnormal3f_vertexbuffer = NULL;
8653 // rsurface.batchnormal3f_bufferoffset = 0;
8654 for (j = 0;j < batchnumvertices;j++)
8656 // if the wavefunc depends on time, evaluate it per-vertex
8659 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8660 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8662 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8664 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8665 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8666 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8668 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8669 // rsurface.batchsvector3f_vertexbuffer = NULL;
8670 // rsurface.batchsvector3f_bufferoffset = 0;
8671 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8672 // rsurface.batchtvector3f_vertexbuffer = NULL;
8673 // rsurface.batchtvector3f_bufferoffset = 0;
8674 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);
8677 case Q3DEFORM_BULGE:
8678 // deform vertex array to make the surface have moving bulges
8679 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8680 // rsurface.batchvertex3f_vertexbuffer = NULL;
8681 // rsurface.batchvertex3f_bufferoffset = 0;
8682 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8683 // rsurface.batchnormal3f_vertexbuffer = NULL;
8684 // rsurface.batchnormal3f_bufferoffset = 0;
8685 for (j = 0;j < batchnumvertices;j++)
8687 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8688 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8690 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8691 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8692 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8694 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8695 // rsurface.batchsvector3f_vertexbuffer = NULL;
8696 // rsurface.batchsvector3f_bufferoffset = 0;
8697 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8698 // rsurface.batchtvector3f_vertexbuffer = NULL;
8699 // rsurface.batchtvector3f_bufferoffset = 0;
8700 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);
8704 // deform vertex array
8705 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8706 break; // if wavefunc is a nop, don't make a dynamic vertex array
8707 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8708 VectorScale(deform->parms, scale, waveparms);
8709 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8710 // rsurface.batchvertex3f_vertexbuffer = NULL;
8711 // rsurface.batchvertex3f_bufferoffset = 0;
8712 for (j = 0;j < batchnumvertices;j++)
8713 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8718 // generate texcoords based on the chosen texcoord source
8719 switch(rsurface.texture->tcgen.tcgen)
8722 case Q3TCGEN_TEXTURE:
8724 case Q3TCGEN_LIGHTMAP:
8725 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8726 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8727 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8728 if (rsurface.batchtexcoordlightmap2f)
8729 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8731 case Q3TCGEN_VECTOR:
8732 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8733 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8734 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8735 for (j = 0;j < batchnumvertices;j++)
8737 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8738 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8741 case Q3TCGEN_ENVIRONMENT:
8742 // make environment reflections using a spheremap
8743 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8744 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8745 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8746 for (j = 0;j < batchnumvertices;j++)
8748 // identical to Q3A's method, but executed in worldspace so
8749 // carried models can be shiny too
8751 float viewer[3], d, reflected[3], worldreflected[3];
8753 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8754 // VectorNormalize(viewer);
8756 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8758 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8759 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8760 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8761 // note: this is proportinal to viewer, so we can normalize later
8763 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8764 VectorNormalize(worldreflected);
8766 // note: this sphere map only uses world x and z!
8767 // so positive and negative y will LOOK THE SAME.
8768 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8769 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8773 // the only tcmod that needs software vertex processing is turbulent, so
8774 // check for it here and apply the changes if needed
8775 // and we only support that as the first one
8776 // (handling a mixture of turbulent and other tcmods would be problematic
8777 // without punting it entirely to a software path)
8778 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8780 amplitude = rsurface.texture->tcmods[0].parms[1];
8781 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8782 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8783 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8784 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8785 for (j = 0;j < batchnumvertices;j++)
8787 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);
8788 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8792 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8794 // convert the modified arrays to vertex structs
8795 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8796 // rsurface.batchvertexmeshbuffer = NULL;
8797 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8798 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8799 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8800 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8801 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8802 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8803 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8805 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8807 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8808 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8811 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8812 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8813 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8814 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8815 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8816 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8817 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8818 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8819 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8823 void RSurf_DrawBatch(void)
8825 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8826 // through the pipeline, killing it earlier in the pipeline would have
8827 // per-surface overhead rather than per-batch overhead, so it's best to
8828 // reject it here, before it hits glDraw.
8829 if (rsurface.batchnumtriangles == 0)
8832 // batch debugging code
8833 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8839 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8840 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8843 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8845 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8847 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8848 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);
8855 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);
8858 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8860 // pick the closest matching water plane
8861 int planeindex, vertexindex, bestplaneindex = -1;
8865 r_waterstate_waterplane_t *p;
8866 qboolean prepared = false;
8868 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8870 if(p->camera_entity != rsurface.texture->camera_entity)
8875 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8877 if(rsurface.batchnumvertices == 0)
8880 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8882 Matrix4x4_Transform(&rsurface.matrix, v, vert);
8883 d += fabs(PlaneDiff(vert, &p->plane));
8885 if (bestd > d || bestplaneindex < 0)
8888 bestplaneindex = planeindex;
8891 return bestplaneindex;
8892 // NOTE: this MAY return a totally unrelated water plane; we can ignore
8893 // this situation though, as it might be better to render single larger
8894 // batches with useless stuff (backface culled for example) than to
8895 // render multiple smaller batches
8898 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8901 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8902 rsurface.passcolor4f_vertexbuffer = 0;
8903 rsurface.passcolor4f_bufferoffset = 0;
8904 for (i = 0;i < rsurface.batchnumvertices;i++)
8905 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8908 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8915 if (rsurface.passcolor4f)
8917 // generate color arrays
8918 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8919 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8920 rsurface.passcolor4f_vertexbuffer = 0;
8921 rsurface.passcolor4f_bufferoffset = 0;
8922 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)
8924 f = RSurf_FogVertex(v);
8933 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8934 rsurface.passcolor4f_vertexbuffer = 0;
8935 rsurface.passcolor4f_bufferoffset = 0;
8936 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8938 f = RSurf_FogVertex(v);
8947 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8954 if (!rsurface.passcolor4f)
8956 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8957 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8958 rsurface.passcolor4f_vertexbuffer = 0;
8959 rsurface.passcolor4f_bufferoffset = 0;
8960 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)
8962 f = RSurf_FogVertex(v);
8963 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8964 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8965 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8970 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
8975 if (!rsurface.passcolor4f)
8977 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8978 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8979 rsurface.passcolor4f_vertexbuffer = 0;
8980 rsurface.passcolor4f_bufferoffset = 0;
8981 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
8990 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
8995 if (!rsurface.passcolor4f)
8997 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8998 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8999 rsurface.passcolor4f_vertexbuffer = 0;
9000 rsurface.passcolor4f_bufferoffset = 0;
9001 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9003 c2[0] = c[0] + r_refdef.scene.ambient;
9004 c2[1] = c[1] + r_refdef.scene.ambient;
9005 c2[2] = c[2] + r_refdef.scene.ambient;
9010 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9013 rsurface.passcolor4f = NULL;
9014 rsurface.passcolor4f_vertexbuffer = 0;
9015 rsurface.passcolor4f_bufferoffset = 0;
9016 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9017 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9018 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9019 GL_Color(r, g, b, a);
9020 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9024 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9026 // TODO: optimize applyfog && applycolor case
9027 // just apply fog if necessary, and tint the fog color array if necessary
9028 rsurface.passcolor4f = NULL;
9029 rsurface.passcolor4f_vertexbuffer = 0;
9030 rsurface.passcolor4f_bufferoffset = 0;
9031 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9032 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9033 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9034 GL_Color(r, g, b, a);
9038 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9041 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9042 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9043 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9044 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9045 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9046 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9047 GL_Color(r, g, b, a);
9051 static void RSurf_DrawBatch_GL11_ClampColor(void)
9056 if (!rsurface.passcolor4f)
9058 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9060 c2[0] = bound(0.0f, c1[0], 1.0f);
9061 c2[1] = bound(0.0f, c1[1], 1.0f);
9062 c2[2] = bound(0.0f, c1[2], 1.0f);
9063 c2[3] = bound(0.0f, c1[3], 1.0f);
9067 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9077 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9078 rsurface.passcolor4f_vertexbuffer = 0;
9079 rsurface.passcolor4f_bufferoffset = 0;
9080 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)
9082 f = -DotProduct(r_refdef.view.forward, n);
9084 f = f * 0.85 + 0.15; // work around so stuff won't get black
9085 f *= r_refdef.lightmapintensity;
9086 Vector4Set(c, f, f, f, 1);
9090 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9092 RSurf_DrawBatch_GL11_ApplyFakeLight();
9093 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9094 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9095 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9096 GL_Color(r, g, b, a);
9100 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9108 vec3_t ambientcolor;
9109 vec3_t diffusecolor;
9113 VectorCopy(rsurface.modellight_lightdir, lightdir);
9114 f = 0.5f * r_refdef.lightmapintensity;
9115 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9116 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9117 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9118 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9119 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9120 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9122 if (VectorLength2(diffusecolor) > 0)
9124 // q3-style directional shading
9125 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9126 rsurface.passcolor4f_vertexbuffer = 0;
9127 rsurface.passcolor4f_bufferoffset = 0;
9128 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)
9130 if ((f = DotProduct(n, lightdir)) > 0)
9131 VectorMA(ambientcolor, f, diffusecolor, c);
9133 VectorCopy(ambientcolor, c);
9140 *applycolor = false;
9144 *r = ambientcolor[0];
9145 *g = ambientcolor[1];
9146 *b = ambientcolor[2];
9147 rsurface.passcolor4f = NULL;
9148 rsurface.passcolor4f_vertexbuffer = 0;
9149 rsurface.passcolor4f_bufferoffset = 0;
9153 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9155 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9156 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9157 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9158 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9159 GL_Color(r, g, b, a);
9163 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9169 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9171 f = 1 - RSurf_FogVertex(v);
9179 void RSurf_SetupDepthAndCulling(void)
9181 // submodels are biased to avoid z-fighting with world surfaces that they
9182 // may be exactly overlapping (avoids z-fighting artifacts on certain
9183 // doors and things in Quake maps)
9184 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9185 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9186 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9187 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9190 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9192 // transparent sky would be ridiculous
9193 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9195 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9196 skyrenderlater = true;
9197 RSurf_SetupDepthAndCulling();
9199 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9200 // skymasking on them, and Quake3 never did sky masking (unlike
9201 // software Quake and software Quake2), so disable the sky masking
9202 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9203 // and skymasking also looks very bad when noclipping outside the
9204 // level, so don't use it then either.
9205 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9207 R_Mesh_ResetTextureState();
9208 if (skyrendermasked)
9210 R_SetupShader_DepthOrShadow();
9211 // depth-only (masking)
9212 GL_ColorMask(0,0,0,0);
9213 // just to make sure that braindead drivers don't draw
9214 // anything despite that colormask...
9215 GL_BlendFunc(GL_ZERO, GL_ONE);
9216 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9217 if (rsurface.batchvertex3fbuffer)
9218 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9220 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9224 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9226 GL_BlendFunc(GL_ONE, GL_ZERO);
9227 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9228 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9229 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9232 if (skyrendermasked)
9233 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9235 R_Mesh_ResetTextureState();
9236 GL_Color(1, 1, 1, 1);
9239 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9240 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9241 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9243 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9247 // render screenspace normalmap to texture
9249 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9254 // bind lightmap texture
9256 // water/refraction/reflection/camera surfaces have to be handled specially
9257 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9259 int start, end, startplaneindex;
9260 for (start = 0;start < texturenumsurfaces;start = end)
9262 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9263 if(startplaneindex < 0)
9265 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9266 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9270 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9272 // now that we have a batch using the same planeindex, render it
9273 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9275 // render water or distortion background
9277 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));
9279 // blend surface on top
9280 GL_DepthMask(false);
9281 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9284 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9286 // render surface with reflection texture as input
9287 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9288 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));
9295 // render surface batch normally
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, texturenumsurfaces, texturesurfacelist, NULL);
9301 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9303 // OpenGL 1.3 path - anything not completely ancient
9304 qboolean applycolor;
9307 const texturelayer_t *layer;
9308 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);
9309 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9311 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9314 int layertexrgbscale;
9315 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9317 if (layerindex == 0)
9321 GL_AlphaTest(false);
9322 GL_DepthFunc(GL_EQUAL);
9325 GL_DepthMask(layer->depthmask && writedepth);
9326 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9327 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9329 layertexrgbscale = 4;
9330 VectorScale(layer->color, 0.25f, layercolor);
9332 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9334 layertexrgbscale = 2;
9335 VectorScale(layer->color, 0.5f, layercolor);
9339 layertexrgbscale = 1;
9340 VectorScale(layer->color, 1.0f, layercolor);
9342 layercolor[3] = layer->color[3];
9343 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9344 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9345 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9346 switch (layer->type)
9348 case TEXTURELAYERTYPE_LITTEXTURE:
9349 // single-pass lightmapped texture with 2x rgbscale
9350 R_Mesh_TexBind(0, r_texture_white);
9351 R_Mesh_TexMatrix(0, NULL);
9352 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9353 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9354 R_Mesh_TexBind(1, layer->texture);
9355 R_Mesh_TexMatrix(1, &layer->texmatrix);
9356 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9357 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9358 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9359 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9360 else if (FAKELIGHT_ENABLED)
9361 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9362 else if (rsurface.uselightmaptexture)
9363 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9365 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9367 case TEXTURELAYERTYPE_TEXTURE:
9368 // singletexture unlit texture with transparency support
9369 R_Mesh_TexBind(0, layer->texture);
9370 R_Mesh_TexMatrix(0, &layer->texmatrix);
9371 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9372 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9373 R_Mesh_TexBind(1, 0);
9374 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9375 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9377 case TEXTURELAYERTYPE_FOG:
9378 // singletexture fogging
9381 R_Mesh_TexBind(0, layer->texture);
9382 R_Mesh_TexMatrix(0, &layer->texmatrix);
9383 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9384 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9388 R_Mesh_TexBind(0, 0);
9389 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9391 R_Mesh_TexBind(1, 0);
9392 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9393 // generate a color array for the fog pass
9394 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9395 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9399 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9402 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9404 GL_DepthFunc(GL_LEQUAL);
9405 GL_AlphaTest(false);
9409 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9411 // OpenGL 1.1 - crusty old voodoo path
9414 const texturelayer_t *layer;
9415 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);
9416 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9418 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9420 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9422 if (layerindex == 0)
9426 GL_AlphaTest(false);
9427 GL_DepthFunc(GL_EQUAL);
9430 GL_DepthMask(layer->depthmask && writedepth);
9431 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9432 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9433 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9434 switch (layer->type)
9436 case TEXTURELAYERTYPE_LITTEXTURE:
9437 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9439 // two-pass lit texture with 2x rgbscale
9440 // first the lightmap pass
9441 R_Mesh_TexBind(0, r_texture_white);
9442 R_Mesh_TexMatrix(0, NULL);
9443 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9444 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9445 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9446 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9447 else if (FAKELIGHT_ENABLED)
9448 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9449 else if (rsurface.uselightmaptexture)
9450 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9452 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9453 // then apply the texture to it
9454 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9455 R_Mesh_TexBind(0, layer->texture);
9456 R_Mesh_TexMatrix(0, &layer->texmatrix);
9457 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9458 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9459 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);
9463 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
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 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9469 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);
9471 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);
9474 case TEXTURELAYERTYPE_TEXTURE:
9475 // singletexture unlit texture with transparency support
9476 R_Mesh_TexBind(0, layer->texture);
9477 R_Mesh_TexMatrix(0, &layer->texmatrix);
9478 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9479 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9480 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);
9482 case TEXTURELAYERTYPE_FOG:
9483 // singletexture fogging
9486 R_Mesh_TexBind(0, layer->texture);
9487 R_Mesh_TexMatrix(0, &layer->texmatrix);
9488 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9489 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9493 R_Mesh_TexBind(0, 0);
9494 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9496 // generate a color array for the fog pass
9497 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9498 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9502 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9505 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9507 GL_DepthFunc(GL_LEQUAL);
9508 GL_AlphaTest(false);
9512 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9516 r_vertexgeneric_t *batchvertex;
9519 // R_Mesh_ResetTextureState();
9520 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9522 if(rsurface.texture && rsurface.texture->currentskinframe)
9524 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9525 c[3] *= rsurface.texture->currentalpha;
9535 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9537 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9538 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9539 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9542 // brighten it up (as texture value 127 means "unlit")
9543 c[0] *= 2 * r_refdef.view.colorscale;
9544 c[1] *= 2 * r_refdef.view.colorscale;
9545 c[2] *= 2 * r_refdef.view.colorscale;
9547 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9548 c[3] *= r_wateralpha.value;
9550 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9552 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9553 GL_DepthMask(false);
9555 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9557 GL_BlendFunc(GL_ONE, GL_ONE);
9558 GL_DepthMask(false);
9560 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9562 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9563 GL_DepthMask(false);
9565 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9567 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9568 GL_DepthMask(false);
9572 GL_BlendFunc(GL_ONE, GL_ZERO);
9573 GL_DepthMask(writedepth);
9576 if (r_showsurfaces.integer == 3)
9578 rsurface.passcolor4f = NULL;
9580 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9582 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9584 rsurface.passcolor4f = NULL;
9585 rsurface.passcolor4f_vertexbuffer = 0;
9586 rsurface.passcolor4f_bufferoffset = 0;
9588 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9590 qboolean applycolor = true;
9593 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9595 r_refdef.lightmapintensity = 1;
9596 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9597 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9599 else if (FAKELIGHT_ENABLED)
9601 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9603 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9604 RSurf_DrawBatch_GL11_ApplyFakeLight();
9605 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9609 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9611 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9612 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9613 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9616 if(!rsurface.passcolor4f)
9617 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9619 RSurf_DrawBatch_GL11_ApplyAmbient();
9620 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9621 if(r_refdef.fogenabled)
9622 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9623 RSurf_DrawBatch_GL11_ClampColor();
9625 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9626 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9629 else if (!r_refdef.view.showdebug)
9631 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9632 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9633 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9635 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9636 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9638 R_Mesh_PrepareVertices_Generic_Unlock();
9641 else if (r_showsurfaces.integer == 4)
9643 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9644 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9645 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9647 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9648 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9649 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9651 R_Mesh_PrepareVertices_Generic_Unlock();
9654 else if (r_showsurfaces.integer == 2)
9657 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9658 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9659 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9661 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9662 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9663 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9664 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9665 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9666 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9667 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9669 R_Mesh_PrepareVertices_Generic_Unlock();
9670 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9674 int texturesurfaceindex;
9676 const msurface_t *surface;
9677 float surfacecolor4f[4];
9678 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9679 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9681 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9683 surface = texturesurfacelist[texturesurfaceindex];
9684 k = (int)(((size_t)surface) / sizeof(msurface_t));
9685 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9686 for (j = 0;j < surface->num_vertices;j++)
9688 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9689 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9693 R_Mesh_PrepareVertices_Generic_Unlock();
9698 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9701 RSurf_SetupDepthAndCulling();
9702 if (r_showsurfaces.integer)
9704 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9707 switch (vid.renderpath)
9709 case RENDERPATH_GL20:
9710 case RENDERPATH_D3D9:
9711 case RENDERPATH_D3D10:
9712 case RENDERPATH_D3D11:
9713 case RENDERPATH_SOFT:
9714 case RENDERPATH_GLES2:
9715 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9717 case RENDERPATH_GL13:
9718 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9720 case RENDERPATH_GL11:
9721 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9727 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9730 RSurf_SetupDepthAndCulling();
9731 if (r_showsurfaces.integer)
9733 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9736 switch (vid.renderpath)
9738 case RENDERPATH_GL20:
9739 case RENDERPATH_D3D9:
9740 case RENDERPATH_D3D10:
9741 case RENDERPATH_D3D11:
9742 case RENDERPATH_SOFT:
9743 case RENDERPATH_GLES2:
9744 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9746 case RENDERPATH_GL13:
9747 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9749 case RENDERPATH_GL11:
9750 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9756 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9759 int texturenumsurfaces, endsurface;
9761 const msurface_t *surface;
9762 #define MAXBATCH_TRANSPARENTSURFACES 256
9763 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9765 // if the model is static it doesn't matter what value we give for
9766 // wantnormals and wanttangents, so this logic uses only rules applicable
9767 // to a model, knowing that they are meaningless otherwise
9768 if (ent == r_refdef.scene.worldentity)
9769 RSurf_ActiveWorldEntity();
9770 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9771 RSurf_ActiveModelEntity(ent, false, false, false);
9774 switch (vid.renderpath)
9776 case RENDERPATH_GL20:
9777 case RENDERPATH_D3D9:
9778 case RENDERPATH_D3D10:
9779 case RENDERPATH_D3D11:
9780 case RENDERPATH_SOFT:
9781 case RENDERPATH_GLES2:
9782 RSurf_ActiveModelEntity(ent, true, true, false);
9784 case RENDERPATH_GL13:
9785 case RENDERPATH_GL11:
9786 RSurf_ActiveModelEntity(ent, true, false, false);
9791 if (r_transparentdepthmasking.integer)
9793 qboolean setup = false;
9794 for (i = 0;i < numsurfaces;i = j)
9797 surface = rsurface.modelsurfaces + surfacelist[i];
9798 texture = surface->texture;
9799 rsurface.texture = R_GetCurrentTexture(texture);
9800 rsurface.lightmaptexture = NULL;
9801 rsurface.deluxemaptexture = NULL;
9802 rsurface.uselightmaptexture = false;
9803 // scan ahead until we find a different texture
9804 endsurface = min(i + 1024, numsurfaces);
9805 texturenumsurfaces = 0;
9806 texturesurfacelist[texturenumsurfaces++] = surface;
9807 for (;j < endsurface;j++)
9809 surface = rsurface.modelsurfaces + surfacelist[j];
9810 if (texture != surface->texture)
9812 texturesurfacelist[texturenumsurfaces++] = surface;
9814 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9816 // render the range of surfaces as depth
9820 GL_ColorMask(0,0,0,0);
9823 GL_BlendFunc(GL_ONE, GL_ZERO);
9825 // R_Mesh_ResetTextureState();
9826 R_SetupShader_DepthOrShadow();
9828 RSurf_SetupDepthAndCulling();
9829 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9830 if (rsurface.batchvertex3fbuffer)
9831 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9833 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9837 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9840 for (i = 0;i < numsurfaces;i = j)
9843 surface = rsurface.modelsurfaces + surfacelist[i];
9844 texture = surface->texture;
9845 rsurface.texture = R_GetCurrentTexture(texture);
9846 // scan ahead until we find a different texture
9847 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9848 texturenumsurfaces = 0;
9849 texturesurfacelist[texturenumsurfaces++] = surface;
9850 if(FAKELIGHT_ENABLED)
9852 rsurface.lightmaptexture = NULL;
9853 rsurface.deluxemaptexture = NULL;
9854 rsurface.uselightmaptexture = false;
9855 for (;j < endsurface;j++)
9857 surface = rsurface.modelsurfaces + surfacelist[j];
9858 if (texture != surface->texture)
9860 texturesurfacelist[texturenumsurfaces++] = surface;
9865 rsurface.lightmaptexture = surface->lightmaptexture;
9866 rsurface.deluxemaptexture = surface->deluxemaptexture;
9867 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9868 for (;j < endsurface;j++)
9870 surface = rsurface.modelsurfaces + surfacelist[j];
9871 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9873 texturesurfacelist[texturenumsurfaces++] = surface;
9876 // render the range of surfaces
9877 if (ent == r_refdef.scene.worldentity)
9878 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9880 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9882 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9885 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9887 // transparent surfaces get pushed off into the transparent queue
9888 int surfacelistindex;
9889 const msurface_t *surface;
9890 vec3_t tempcenter, center;
9891 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9893 surface = texturesurfacelist[surfacelistindex];
9894 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9895 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9896 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9897 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9898 if (queueentity->transparent_offset) // transparent offset
9900 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9901 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9902 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9904 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9908 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9910 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9912 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9914 RSurf_SetupDepthAndCulling();
9915 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9916 if (rsurface.batchvertex3fbuffer)
9917 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9919 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9923 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9925 const entity_render_t *queueentity = r_refdef.scene.worldentity;
9928 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9931 if (!rsurface.texture->currentnumlayers)
9933 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9934 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9936 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9938 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9939 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9940 else if (!rsurface.texture->currentnumlayers)
9942 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9944 // in the deferred case, transparent surfaces were queued during prepass
9945 if (!r_shadow_usingdeferredprepass)
9946 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9950 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9951 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9956 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9960 R_FrameData_SetMark();
9961 // break the surface list down into batches by texture and use of lightmapping
9962 for (i = 0;i < numsurfaces;i = j)
9965 // texture is the base texture pointer, rsurface.texture is the
9966 // current frame/skin the texture is directing us to use (for example
9967 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9968 // use skin 1 instead)
9969 texture = surfacelist[i]->texture;
9970 rsurface.texture = R_GetCurrentTexture(texture);
9971 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9973 // if this texture is not the kind we want, skip ahead to the next one
9974 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9978 if(FAKELIGHT_ENABLED || depthonly || prepass)
9980 rsurface.lightmaptexture = NULL;
9981 rsurface.deluxemaptexture = NULL;
9982 rsurface.uselightmaptexture = false;
9983 // simply scan ahead until we find a different texture or lightmap state
9984 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9989 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
9990 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
9991 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
9992 // simply scan ahead until we find a different texture or lightmap state
9993 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
9996 // render the range of surfaces
9997 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
9999 R_FrameData_ReturnToMark();
10002 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10006 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10009 if (!rsurface.texture->currentnumlayers)
10011 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10012 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10014 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10016 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10017 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10018 else if (!rsurface.texture->currentnumlayers)
10020 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10022 // in the deferred case, transparent surfaces were queued during prepass
10023 if (!r_shadow_usingdeferredprepass)
10024 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10028 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10029 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10034 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10037 texture_t *texture;
10038 R_FrameData_SetMark();
10039 // break the surface list down into batches by texture and use of lightmapping
10040 for (i = 0;i < numsurfaces;i = j)
10043 // texture is the base texture pointer, rsurface.texture is the
10044 // current frame/skin the texture is directing us to use (for example
10045 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10046 // use skin 1 instead)
10047 texture = surfacelist[i]->texture;
10048 rsurface.texture = R_GetCurrentTexture(texture);
10049 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10051 // if this texture is not the kind we want, skip ahead to the next one
10052 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10056 if(FAKELIGHT_ENABLED || depthonly || prepass)
10058 rsurface.lightmaptexture = NULL;
10059 rsurface.deluxemaptexture = NULL;
10060 rsurface.uselightmaptexture = false;
10061 // simply scan ahead until we find a different texture or lightmap state
10062 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10067 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10068 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10069 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10070 // simply scan ahead until we find a different texture or lightmap state
10071 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10074 // render the range of surfaces
10075 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10077 R_FrameData_ReturnToMark();
10080 float locboxvertex3f[6*4*3] =
10082 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10083 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10084 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10085 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10086 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10087 1,0,0, 0,0,0, 0,1,0, 1,1,0
10090 unsigned short locboxelements[6*2*3] =
10095 12,13,14, 12,14,15,
10096 16,17,18, 16,18,19,
10100 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10103 cl_locnode_t *loc = (cl_locnode_t *)ent;
10105 float vertex3f[6*4*3];
10107 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10108 GL_DepthMask(false);
10109 GL_DepthRange(0, 1);
10110 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10111 GL_DepthTest(true);
10112 GL_CullFace(GL_NONE);
10113 R_EntityMatrix(&identitymatrix);
10115 // R_Mesh_ResetTextureState();
10117 i = surfacelist[0];
10118 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10119 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10120 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10121 surfacelist[0] < 0 ? 0.5f : 0.125f);
10123 if (VectorCompare(loc->mins, loc->maxs))
10125 VectorSet(size, 2, 2, 2);
10126 VectorMA(loc->mins, -0.5f, size, mins);
10130 VectorCopy(loc->mins, mins);
10131 VectorSubtract(loc->maxs, loc->mins, size);
10134 for (i = 0;i < 6*4*3;)
10135 for (j = 0;j < 3;j++, i++)
10136 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10138 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10139 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10140 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10143 void R_DrawLocs(void)
10146 cl_locnode_t *loc, *nearestloc;
10148 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10149 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10151 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10152 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10156 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10158 if (decalsystem->decals)
10159 Mem_Free(decalsystem->decals);
10160 memset(decalsystem, 0, sizeof(*decalsystem));
10163 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)
10166 tridecal_t *decals;
10169 // expand or initialize the system
10170 if (decalsystem->maxdecals <= decalsystem->numdecals)
10172 decalsystem_t old = *decalsystem;
10173 qboolean useshortelements;
10174 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10175 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10176 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)));
10177 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10178 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10179 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10180 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10181 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10182 if (decalsystem->numdecals)
10183 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10185 Mem_Free(old.decals);
10186 for (i = 0;i < decalsystem->maxdecals*3;i++)
10187 decalsystem->element3i[i] = i;
10188 if (useshortelements)
10189 for (i = 0;i < decalsystem->maxdecals*3;i++)
10190 decalsystem->element3s[i] = i;
10193 // grab a decal and search for another free slot for the next one
10194 decals = decalsystem->decals;
10195 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10196 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10198 decalsystem->freedecal = i;
10199 if (decalsystem->numdecals <= i)
10200 decalsystem->numdecals = i + 1;
10202 // initialize the decal
10204 decal->triangleindex = triangleindex;
10205 decal->surfaceindex = surfaceindex;
10206 decal->decalsequence = decalsequence;
10207 decal->color4f[0][0] = c0[0];
10208 decal->color4f[0][1] = c0[1];
10209 decal->color4f[0][2] = c0[2];
10210 decal->color4f[0][3] = 1;
10211 decal->color4f[1][0] = c1[0];
10212 decal->color4f[1][1] = c1[1];
10213 decal->color4f[1][2] = c1[2];
10214 decal->color4f[1][3] = 1;
10215 decal->color4f[2][0] = c2[0];
10216 decal->color4f[2][1] = c2[1];
10217 decal->color4f[2][2] = c2[2];
10218 decal->color4f[2][3] = 1;
10219 decal->vertex3f[0][0] = v0[0];
10220 decal->vertex3f[0][1] = v0[1];
10221 decal->vertex3f[0][2] = v0[2];
10222 decal->vertex3f[1][0] = v1[0];
10223 decal->vertex3f[1][1] = v1[1];
10224 decal->vertex3f[1][2] = v1[2];
10225 decal->vertex3f[2][0] = v2[0];
10226 decal->vertex3f[2][1] = v2[1];
10227 decal->vertex3f[2][2] = v2[2];
10228 decal->texcoord2f[0][0] = t0[0];
10229 decal->texcoord2f[0][1] = t0[1];
10230 decal->texcoord2f[1][0] = t1[0];
10231 decal->texcoord2f[1][1] = t1[1];
10232 decal->texcoord2f[2][0] = t2[0];
10233 decal->texcoord2f[2][1] = t2[1];
10236 extern cvar_t cl_decals_bias;
10237 extern cvar_t cl_decals_models;
10238 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10239 // baseparms, parms, temps
10240 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)
10245 const float *vertex3f;
10246 const float *normal3f;
10248 float points[2][9][3];
10255 e = rsurface.modelelement3i + 3*triangleindex;
10257 vertex3f = rsurface.modelvertex3f;
10258 normal3f = rsurface.modelnormal3f;
10260 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10262 index = 3*e[cornerindex];
10263 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10266 //TriangleNormal(v[0], v[1], v[2], normal);
10267 //if (DotProduct(normal, localnormal) < 0.0f)
10269 // clip by each of the box planes formed from the projection matrix
10270 // if anything survives, we emit the decal
10271 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]);
10274 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]);
10277 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]);
10280 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]);
10283 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]);
10286 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]);
10289 // some part of the triangle survived, so we have to accept it...
10292 // dynamic always uses the original triangle
10294 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10296 index = 3*e[cornerindex];
10297 VectorCopy(vertex3f + index, v[cornerindex]);
10300 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10302 // convert vertex positions to texcoords
10303 Matrix4x4_Transform(projection, v[cornerindex], temp);
10304 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10305 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10306 // calculate distance fade from the projection origin
10307 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10308 f = bound(0.0f, f, 1.0f);
10309 c[cornerindex][0] = r * f;
10310 c[cornerindex][1] = g * f;
10311 c[cornerindex][2] = b * f;
10312 c[cornerindex][3] = 1.0f;
10313 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10316 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);
10318 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10319 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);
10321 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)
10323 matrix4x4_t projection;
10324 decalsystem_t *decalsystem;
10327 const msurface_t *surface;
10328 const msurface_t *surfaces;
10329 const int *surfacelist;
10330 const texture_t *texture;
10332 int numsurfacelist;
10333 int surfacelistindex;
10336 float localorigin[3];
10337 float localnormal[3];
10338 float localmins[3];
10339 float localmaxs[3];
10342 float planes[6][4];
10345 int bih_triangles_count;
10346 int bih_triangles[256];
10347 int bih_surfaces[256];
10349 decalsystem = &ent->decalsystem;
10350 model = ent->model;
10351 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10353 R_DecalSystem_Reset(&ent->decalsystem);
10357 if (!model->brush.data_leafs && !cl_decals_models.integer)
10359 if (decalsystem->model)
10360 R_DecalSystem_Reset(decalsystem);
10364 if (decalsystem->model != model)
10365 R_DecalSystem_Reset(decalsystem);
10366 decalsystem->model = model;
10368 RSurf_ActiveModelEntity(ent, true, false, false);
10370 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10371 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10372 VectorNormalize(localnormal);
10373 localsize = worldsize*rsurface.inversematrixscale;
10374 localmins[0] = localorigin[0] - localsize;
10375 localmins[1] = localorigin[1] - localsize;
10376 localmins[2] = localorigin[2] - localsize;
10377 localmaxs[0] = localorigin[0] + localsize;
10378 localmaxs[1] = localorigin[1] + localsize;
10379 localmaxs[2] = localorigin[2] + localsize;
10381 //VectorCopy(localnormal, planes[4]);
10382 //VectorVectors(planes[4], planes[2], planes[0]);
10383 AnglesFromVectors(angles, localnormal, NULL, false);
10384 AngleVectors(angles, planes[0], planes[2], planes[4]);
10385 VectorNegate(planes[0], planes[1]);
10386 VectorNegate(planes[2], planes[3]);
10387 VectorNegate(planes[4], planes[5]);
10388 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10389 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10390 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10391 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10392 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10393 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10398 matrix4x4_t forwardprojection;
10399 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10400 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10405 float projectionvector[4][3];
10406 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10407 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10408 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10409 projectionvector[0][0] = planes[0][0] * ilocalsize;
10410 projectionvector[0][1] = planes[1][0] * ilocalsize;
10411 projectionvector[0][2] = planes[2][0] * ilocalsize;
10412 projectionvector[1][0] = planes[0][1] * ilocalsize;
10413 projectionvector[1][1] = planes[1][1] * ilocalsize;
10414 projectionvector[1][2] = planes[2][1] * ilocalsize;
10415 projectionvector[2][0] = planes[0][2] * ilocalsize;
10416 projectionvector[2][1] = planes[1][2] * ilocalsize;
10417 projectionvector[2][2] = planes[2][2] * ilocalsize;
10418 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10419 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10420 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10421 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10425 dynamic = model->surfmesh.isanimated;
10426 numsurfacelist = model->nummodelsurfaces;
10427 surfacelist = model->sortedmodelsurfaces;
10428 surfaces = model->data_surfaces;
10431 bih_triangles_count = -1;
10434 if(model->render_bih.numleafs)
10435 bih = &model->render_bih;
10436 else if(model->collision_bih.numleafs)
10437 bih = &model->collision_bih;
10440 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10441 if(bih_triangles_count == 0)
10443 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10445 if(bih_triangles_count > 0)
10447 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10449 surfaceindex = bih_surfaces[triangleindex];
10450 surface = surfaces + surfaceindex;
10451 texture = surface->texture;
10452 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10454 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10456 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10461 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10463 surfaceindex = surfacelist[surfacelistindex];
10464 surface = surfaces + surfaceindex;
10465 // check cull box first because it rejects more than any other check
10466 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10468 // skip transparent surfaces
10469 texture = surface->texture;
10470 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10472 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10474 numtriangles = surface->num_triangles;
10475 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10476 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10481 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10482 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)
10484 int renderentityindex;
10485 float worldmins[3];
10486 float worldmaxs[3];
10487 entity_render_t *ent;
10489 if (!cl_decals_newsystem.integer)
10492 worldmins[0] = worldorigin[0] - worldsize;
10493 worldmins[1] = worldorigin[1] - worldsize;
10494 worldmins[2] = worldorigin[2] - worldsize;
10495 worldmaxs[0] = worldorigin[0] + worldsize;
10496 worldmaxs[1] = worldorigin[1] + worldsize;
10497 worldmaxs[2] = worldorigin[2] + worldsize;
10499 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10501 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10503 ent = r_refdef.scene.entities[renderentityindex];
10504 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10507 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10511 typedef struct r_decalsystem_splatqueue_s
10513 vec3_t worldorigin;
10514 vec3_t worldnormal;
10520 r_decalsystem_splatqueue_t;
10522 int r_decalsystem_numqueued = 0;
10523 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10525 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)
10527 r_decalsystem_splatqueue_t *queue;
10529 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10532 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10533 VectorCopy(worldorigin, queue->worldorigin);
10534 VectorCopy(worldnormal, queue->worldnormal);
10535 Vector4Set(queue->color, r, g, b, a);
10536 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10537 queue->worldsize = worldsize;
10538 queue->decalsequence = cl.decalsequence++;
10541 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10544 r_decalsystem_splatqueue_t *queue;
10546 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10547 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);
10548 r_decalsystem_numqueued = 0;
10551 extern cvar_t cl_decals_max;
10552 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10555 decalsystem_t *decalsystem = &ent->decalsystem;
10562 if (!decalsystem->numdecals)
10565 if (r_showsurfaces.integer)
10568 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10570 R_DecalSystem_Reset(decalsystem);
10574 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10575 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10577 if (decalsystem->lastupdatetime)
10578 frametime = (cl.time - decalsystem->lastupdatetime);
10581 decalsystem->lastupdatetime = cl.time;
10582 decal = decalsystem->decals;
10583 numdecals = decalsystem->numdecals;
10585 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10587 if (decal->color4f[0][3])
10589 decal->lived += frametime;
10590 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10592 memset(decal, 0, sizeof(*decal));
10593 if (decalsystem->freedecal > i)
10594 decalsystem->freedecal = i;
10598 decal = decalsystem->decals;
10599 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10602 // collapse the array by shuffling the tail decals into the gaps
10605 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10606 decalsystem->freedecal++;
10607 if (decalsystem->freedecal == numdecals)
10609 decal[decalsystem->freedecal] = decal[--numdecals];
10612 decalsystem->numdecals = numdecals;
10614 if (numdecals <= 0)
10616 // if there are no decals left, reset decalsystem
10617 R_DecalSystem_Reset(decalsystem);
10621 extern skinframe_t *decalskinframe;
10622 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10625 decalsystem_t *decalsystem = &ent->decalsystem;
10634 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10637 numdecals = decalsystem->numdecals;
10641 if (r_showsurfaces.integer)
10644 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10646 R_DecalSystem_Reset(decalsystem);
10650 // if the model is static it doesn't matter what value we give for
10651 // wantnormals and wanttangents, so this logic uses only rules applicable
10652 // to a model, knowing that they are meaningless otherwise
10653 if (ent == r_refdef.scene.worldentity)
10654 RSurf_ActiveWorldEntity();
10656 RSurf_ActiveModelEntity(ent, false, false, false);
10658 decalsystem->lastupdatetime = cl.time;
10659 decal = decalsystem->decals;
10661 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10663 // update vertex positions for animated models
10664 v3f = decalsystem->vertex3f;
10665 c4f = decalsystem->color4f;
10666 t2f = decalsystem->texcoord2f;
10667 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10669 if (!decal->color4f[0][3])
10672 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10675 // update color values for fading decals
10676 if (decal->lived >= cl_decals_time.value)
10677 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10681 c4f[ 0] = decal->color4f[0][0] * alpha;
10682 c4f[ 1] = decal->color4f[0][1] * alpha;
10683 c4f[ 2] = decal->color4f[0][2] * alpha;
10685 c4f[ 4] = decal->color4f[1][0] * alpha;
10686 c4f[ 5] = decal->color4f[1][1] * alpha;
10687 c4f[ 6] = decal->color4f[1][2] * alpha;
10689 c4f[ 8] = decal->color4f[2][0] * alpha;
10690 c4f[ 9] = decal->color4f[2][1] * alpha;
10691 c4f[10] = decal->color4f[2][2] * alpha;
10694 t2f[0] = decal->texcoord2f[0][0];
10695 t2f[1] = decal->texcoord2f[0][1];
10696 t2f[2] = decal->texcoord2f[1][0];
10697 t2f[3] = decal->texcoord2f[1][1];
10698 t2f[4] = decal->texcoord2f[2][0];
10699 t2f[5] = decal->texcoord2f[2][1];
10701 // update vertex positions for animated models
10702 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10704 e = rsurface.modelelement3i + 3*decal->triangleindex;
10705 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10706 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10707 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10711 VectorCopy(decal->vertex3f[0], v3f);
10712 VectorCopy(decal->vertex3f[1], v3f + 3);
10713 VectorCopy(decal->vertex3f[2], v3f + 6);
10716 if (r_refdef.fogenabled)
10718 alpha = RSurf_FogVertex(v3f);
10719 VectorScale(c4f, alpha, c4f);
10720 alpha = RSurf_FogVertex(v3f + 3);
10721 VectorScale(c4f + 4, alpha, c4f + 4);
10722 alpha = RSurf_FogVertex(v3f + 6);
10723 VectorScale(c4f + 8, alpha, c4f + 8);
10734 r_refdef.stats.drawndecals += numtris;
10736 // now render the decals all at once
10737 // (this assumes they all use one particle font texture!)
10738 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);
10739 // R_Mesh_ResetTextureState();
10740 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10741 GL_DepthMask(false);
10742 GL_DepthRange(0, 1);
10743 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10744 GL_DepthTest(true);
10745 GL_CullFace(GL_NONE);
10746 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10747 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10748 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10752 static void R_DrawModelDecals(void)
10756 // fade faster when there are too many decals
10757 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10758 for (i = 0;i < r_refdef.scene.numentities;i++)
10759 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10761 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10762 for (i = 0;i < r_refdef.scene.numentities;i++)
10763 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10764 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10766 R_DecalSystem_ApplySplatEntitiesQueue();
10768 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10769 for (i = 0;i < r_refdef.scene.numentities;i++)
10770 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10772 r_refdef.stats.totaldecals += numdecals;
10774 if (r_showsurfaces.integer)
10777 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10779 for (i = 0;i < r_refdef.scene.numentities;i++)
10781 if (!r_refdef.viewcache.entityvisible[i])
10783 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10784 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10788 extern cvar_t mod_collision_bih;
10789 void R_DrawDebugModel(void)
10791 entity_render_t *ent = rsurface.entity;
10792 int i, j, k, l, flagsmask;
10793 const msurface_t *surface;
10794 dp_model_t *model = ent->model;
10797 switch(vid.renderpath)
10799 case RENDERPATH_GL11:
10800 case RENDERPATH_GL13:
10801 case RENDERPATH_GL20:
10803 case RENDERPATH_D3D9:
10804 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10806 case RENDERPATH_D3D10:
10807 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10809 case RENDERPATH_D3D11:
10810 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10812 case RENDERPATH_SOFT:
10813 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10815 case RENDERPATH_GLES2:
10816 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10820 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10822 // R_Mesh_ResetTextureState();
10823 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10824 GL_DepthRange(0, 1);
10825 GL_DepthTest(!r_showdisabledepthtest.integer);
10826 GL_DepthMask(false);
10827 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10829 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10833 qboolean cullbox = ent == r_refdef.scene.worldentity;
10834 const q3mbrush_t *brush;
10835 const bih_t *bih = &model->collision_bih;
10836 const bih_leaf_t *bihleaf;
10837 float vertex3f[3][3];
10838 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10840 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10842 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10844 switch (bihleaf->type)
10847 brush = model->brush.data_brushes + bihleaf->itemindex;
10848 if (brush->colbrushf && brush->colbrushf->numtriangles)
10850 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);
10851 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10852 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10855 case BIH_COLLISIONTRIANGLE:
10856 triangleindex = bihleaf->itemindex;
10857 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10858 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10859 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10860 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);
10861 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10862 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10864 case BIH_RENDERTRIANGLE:
10865 triangleindex = bihleaf->itemindex;
10866 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10867 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10868 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[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);
10877 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10879 if (r_showtris.integer || (r_shownormals.value != 0))
10881 if (r_showdisabledepthtest.integer)
10883 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10884 GL_DepthMask(false);
10888 GL_BlendFunc(GL_ONE, GL_ZERO);
10889 GL_DepthMask(true);
10891 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10893 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10895 rsurface.texture = R_GetCurrentTexture(surface->texture);
10896 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10898 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10899 if (r_showtris.value > 0)
10901 if (!rsurface.texture->currentlayers->depthmask)
10902 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10903 else if (ent == r_refdef.scene.worldentity)
10904 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10906 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10907 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10908 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10910 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10913 if (r_shownormals.value < 0)
10915 qglBegin(GL_LINES);
10916 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10918 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10919 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10920 qglVertex3f(v[0], v[1], v[2]);
10921 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10922 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10923 qglVertex3f(v[0], v[1], v[2]);
10928 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10930 qglBegin(GL_LINES);
10931 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10933 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10934 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10935 qglVertex3f(v[0], v[1], v[2]);
10936 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10937 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10938 qglVertex3f(v[0], v[1], v[2]);
10942 qglBegin(GL_LINES);
10943 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10945 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10946 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10947 qglVertex3f(v[0], v[1], v[2]);
10948 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10949 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10950 qglVertex3f(v[0], v[1], v[2]);
10954 qglBegin(GL_LINES);
10955 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10957 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10958 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10959 qglVertex3f(v[0], v[1], v[2]);
10960 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10961 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10962 qglVertex3f(v[0], v[1], v[2]);
10969 rsurface.texture = NULL;
10973 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10974 int r_maxsurfacelist = 0;
10975 const msurface_t **r_surfacelist = NULL;
10976 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10978 int i, j, endj, flagsmask;
10979 dp_model_t *model = r_refdef.scene.worldmodel;
10980 msurface_t *surfaces;
10981 unsigned char *update;
10982 int numsurfacelist = 0;
10986 if (r_maxsurfacelist < model->num_surfaces)
10988 r_maxsurfacelist = model->num_surfaces;
10990 Mem_Free((msurface_t**)r_surfacelist);
10991 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10994 RSurf_ActiveWorldEntity();
10996 surfaces = model->data_surfaces;
10997 update = model->brushq1.lightmapupdateflags;
10999 // update light styles on this submodel
11000 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11002 model_brush_lightstyleinfo_t *style;
11003 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11005 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11007 int *list = style->surfacelist;
11008 style->value = r_refdef.scene.lightstylevalue[style->style];
11009 for (j = 0;j < style->numsurfaces;j++)
11010 update[list[j]] = true;
11015 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11019 R_DrawDebugModel();
11020 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11024 rsurface.lightmaptexture = NULL;
11025 rsurface.deluxemaptexture = NULL;
11026 rsurface.uselightmaptexture = false;
11027 rsurface.texture = NULL;
11028 rsurface.rtlight = NULL;
11029 numsurfacelist = 0;
11030 // add visible surfaces to draw list
11031 for (i = 0;i < model->nummodelsurfaces;i++)
11033 j = model->sortedmodelsurfaces[i];
11034 if (r_refdef.viewcache.world_surfacevisible[j])
11035 r_surfacelist[numsurfacelist++] = surfaces + j;
11037 // update lightmaps if needed
11038 if (model->brushq1.firstrender)
11040 model->brushq1.firstrender = false;
11041 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11043 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11047 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11048 if (r_refdef.viewcache.world_surfacevisible[j])
11050 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11052 // don't do anything if there were no surfaces
11053 if (!numsurfacelist)
11055 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11058 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11060 // add to stats if desired
11061 if (r_speeds.integer && !skysurfaces && !depthonly)
11063 r_refdef.stats.world_surfaces += numsurfacelist;
11064 for (j = 0;j < numsurfacelist;j++)
11065 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11068 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11071 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11073 int i, j, endj, flagsmask;
11074 dp_model_t *model = ent->model;
11075 msurface_t *surfaces;
11076 unsigned char *update;
11077 int numsurfacelist = 0;
11081 if (r_maxsurfacelist < model->num_surfaces)
11083 r_maxsurfacelist = model->num_surfaces;
11085 Mem_Free((msurface_t **)r_surfacelist);
11086 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11089 // if the model is static it doesn't matter what value we give for
11090 // wantnormals and wanttangents, so this logic uses only rules applicable
11091 // to a model, knowing that they are meaningless otherwise
11092 if (ent == r_refdef.scene.worldentity)
11093 RSurf_ActiveWorldEntity();
11094 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11095 RSurf_ActiveModelEntity(ent, false, false, false);
11097 RSurf_ActiveModelEntity(ent, true, true, true);
11098 else if (depthonly)
11100 switch (vid.renderpath)
11102 case RENDERPATH_GL20:
11103 case RENDERPATH_D3D9:
11104 case RENDERPATH_D3D10:
11105 case RENDERPATH_D3D11:
11106 case RENDERPATH_SOFT:
11107 case RENDERPATH_GLES2:
11108 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11110 case RENDERPATH_GL13:
11111 case RENDERPATH_GL11:
11112 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11118 switch (vid.renderpath)
11120 case RENDERPATH_GL20:
11121 case RENDERPATH_D3D9:
11122 case RENDERPATH_D3D10:
11123 case RENDERPATH_D3D11:
11124 case RENDERPATH_SOFT:
11125 case RENDERPATH_GLES2:
11126 RSurf_ActiveModelEntity(ent, true, true, false);
11128 case RENDERPATH_GL13:
11129 case RENDERPATH_GL11:
11130 RSurf_ActiveModelEntity(ent, true, false, false);
11135 surfaces = model->data_surfaces;
11136 update = model->brushq1.lightmapupdateflags;
11138 // update light styles
11139 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11141 model_brush_lightstyleinfo_t *style;
11142 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11144 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11146 int *list = style->surfacelist;
11147 style->value = r_refdef.scene.lightstylevalue[style->style];
11148 for (j = 0;j < style->numsurfaces;j++)
11149 update[list[j]] = true;
11154 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11158 R_DrawDebugModel();
11159 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11163 rsurface.lightmaptexture = NULL;
11164 rsurface.deluxemaptexture = NULL;
11165 rsurface.uselightmaptexture = false;
11166 rsurface.texture = NULL;
11167 rsurface.rtlight = NULL;
11168 numsurfacelist = 0;
11169 // add visible surfaces to draw list
11170 for (i = 0;i < model->nummodelsurfaces;i++)
11171 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11172 // don't do anything if there were no surfaces
11173 if (!numsurfacelist)
11175 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11178 // update lightmaps if needed
11182 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11187 R_BuildLightMap(ent, surfaces + j);
11192 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11194 R_BuildLightMap(ent, surfaces + j);
11195 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11197 // add to stats if desired
11198 if (r_speeds.integer && !skysurfaces && !depthonly)
11200 r_refdef.stats.entities_surfaces += numsurfacelist;
11201 for (j = 0;j < numsurfacelist;j++)
11202 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11205 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11208 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11210 static texture_t texture;
11211 static msurface_t surface;
11212 const msurface_t *surfacelist = &surface;
11214 // fake enough texture and surface state to render this geometry
11216 texture.update_lastrenderframe = -1; // regenerate this texture
11217 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11218 texture.currentskinframe = skinframe;
11219 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11220 texture.offsetmapping = OFFSETMAPPING_OFF;
11221 texture.offsetscale = 1;
11222 texture.specularscalemod = 1;
11223 texture.specularpowermod = 1;
11225 surface.texture = &texture;
11226 surface.num_triangles = numtriangles;
11227 surface.num_firsttriangle = firsttriangle;
11228 surface.num_vertices = numvertices;
11229 surface.num_firstvertex = firstvertex;
11232 rsurface.texture = R_GetCurrentTexture(surface.texture);
11233 rsurface.lightmaptexture = NULL;
11234 rsurface.deluxemaptexture = NULL;
11235 rsurface.uselightmaptexture = false;
11236 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11239 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)
11241 static msurface_t surface;
11242 const msurface_t *surfacelist = &surface;
11244 // fake enough texture and surface state to render this geometry
11245 surface.texture = texture;
11246 surface.num_triangles = numtriangles;
11247 surface.num_firsttriangle = firsttriangle;
11248 surface.num_vertices = numvertices;
11249 surface.num_firstvertex = firstvertex;
11252 rsurface.texture = R_GetCurrentTexture(surface.texture);
11253 rsurface.lightmaptexture = NULL;
11254 rsurface.deluxemaptexture = NULL;
11255 rsurface.uselightmaptexture = false;
11256 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);