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 USEGAMMARAMPS\n", " gammaramps"},
637 {"#define USECUBEFILTER\n", " cubefilter"},
638 {"#define USEGLOW\n", " glow"},
639 {"#define USEBLOOM\n", " bloom"},
640 {"#define USESPECULAR\n", " specular"},
641 {"#define USEPOSTPROCESSING\n", " postprocessing"},
642 {"#define USEREFLECTION\n", " reflection"},
643 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
644 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
645 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
646 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
647 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
648 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
649 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
650 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
651 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
652 {"#define USEALPHAKILL\n", " alphakill"},
653 {"#define USEREFLECTCUBE\n", " reflectcube"},
654 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
655 {"#define USEBOUNCEGRID\n", " bouncegrid"},
658 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
659 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
661 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
662 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
663 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
664 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
665 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
666 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
667 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
668 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
669 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
670 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
671 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
672 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
673 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
674 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
675 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
676 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
679 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
681 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
682 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
683 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
684 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
685 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
686 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
687 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
688 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
689 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
690 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
691 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
692 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
693 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
694 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
695 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
696 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
699 struct r_glsl_permutation_s;
700 typedef struct r_glsl_permutation_s
703 struct r_glsl_permutation_s *hashnext;
705 unsigned int permutation;
707 /// indicates if we have tried compiling this permutation already
709 /// 0 if compilation failed
711 // texture units assigned to each detected uniform
712 int tex_Texture_First;
713 int tex_Texture_Second;
714 int tex_Texture_GammaRamps;
715 int tex_Texture_Normal;
716 int tex_Texture_Color;
717 int tex_Texture_Gloss;
718 int tex_Texture_Glow;
719 int tex_Texture_SecondaryNormal;
720 int tex_Texture_SecondaryColor;
721 int tex_Texture_SecondaryGloss;
722 int tex_Texture_SecondaryGlow;
723 int tex_Texture_Pants;
724 int tex_Texture_Shirt;
725 int tex_Texture_FogHeightTexture;
726 int tex_Texture_FogMask;
727 int tex_Texture_Lightmap;
728 int tex_Texture_Deluxemap;
729 int tex_Texture_Attenuation;
730 int tex_Texture_Cube;
731 int tex_Texture_Refraction;
732 int tex_Texture_Reflection;
733 int tex_Texture_ShadowMap2D;
734 int tex_Texture_CubeProjection;
735 int tex_Texture_ScreenDepth;
736 int tex_Texture_ScreenNormalMap;
737 int tex_Texture_ScreenDiffuse;
738 int tex_Texture_ScreenSpecular;
739 int tex_Texture_ReflectMask;
740 int tex_Texture_ReflectCube;
741 int tex_Texture_BounceGrid;
742 /// locations of detected uniforms in program object, or -1 if not found
743 int loc_Texture_First;
744 int loc_Texture_Second;
745 int loc_Texture_GammaRamps;
746 int loc_Texture_Normal;
747 int loc_Texture_Color;
748 int loc_Texture_Gloss;
749 int loc_Texture_Glow;
750 int loc_Texture_SecondaryNormal;
751 int loc_Texture_SecondaryColor;
752 int loc_Texture_SecondaryGloss;
753 int loc_Texture_SecondaryGlow;
754 int loc_Texture_Pants;
755 int loc_Texture_Shirt;
756 int loc_Texture_FogHeightTexture;
757 int loc_Texture_FogMask;
758 int loc_Texture_Lightmap;
759 int loc_Texture_Deluxemap;
760 int loc_Texture_Attenuation;
761 int loc_Texture_Cube;
762 int loc_Texture_Refraction;
763 int loc_Texture_Reflection;
764 int loc_Texture_ShadowMap2D;
765 int loc_Texture_CubeProjection;
766 int loc_Texture_ScreenDepth;
767 int loc_Texture_ScreenNormalMap;
768 int loc_Texture_ScreenDiffuse;
769 int loc_Texture_ScreenSpecular;
770 int loc_Texture_ReflectMask;
771 int loc_Texture_ReflectCube;
772 int loc_Texture_BounceGrid;
774 int loc_BloomBlur_Parameters;
776 int loc_Color_Ambient;
777 int loc_Color_Diffuse;
778 int loc_Color_Specular;
782 int loc_DeferredColor_Ambient;
783 int loc_DeferredColor_Diffuse;
784 int loc_DeferredColor_Specular;
785 int loc_DeferredMod_Diffuse;
786 int loc_DeferredMod_Specular;
787 int loc_DistortScaleRefractReflect;
790 int loc_FogHeightFade;
792 int loc_FogPlaneViewDist;
793 int loc_FogRangeRecip;
796 int loc_LightPosition;
797 int loc_OffsetMapping_Scale;
799 int loc_ReflectColor;
800 int loc_ReflectFactor;
801 int loc_ReflectOffset;
802 int loc_RefractColor;
804 int loc_ScreenCenterRefractReflect;
805 int loc_ScreenScaleRefractReflect;
806 int loc_ScreenToDepth;
807 int loc_ShadowMap_Parameters;
808 int loc_ShadowMap_TextureScale;
809 int loc_SpecularPower;
814 int loc_ViewTintColor;
816 int loc_ModelToLight;
818 int loc_BackgroundTexMatrix;
819 int loc_ModelViewProjectionMatrix;
820 int loc_ModelViewMatrix;
821 int loc_PixelToScreenTexCoord;
822 int loc_ModelToReflectCube;
823 int loc_ShadowMapMatrix;
824 int loc_BloomColorSubtract;
825 int loc_NormalmapScrollBlend;
826 int loc_BounceGridMatrix;
827 int loc_BounceGridIntensity;
829 r_glsl_permutation_t;
831 #define SHADERPERMUTATION_HASHSIZE 256
834 // non-degradable "lightweight" shader parameters to keep the permutations simpler
835 // these can NOT degrade! only use for simple stuff
838 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
839 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
840 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
841 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
842 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
843 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
845 #define SHADERSTATICPARMS_COUNT 6
847 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
848 static int shaderstaticparms_count = 0;
850 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
851 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
852 qboolean R_CompileShader_CheckStaticParms(void)
854 static int r_compileshader_staticparms_save[1];
855 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
856 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
859 if (r_glsl_saturation_redcompensate.integer)
860 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
861 if (r_shadow_glossexact.integer)
862 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
863 if (r_glsl_postprocess.integer)
865 if (r_glsl_postprocess_uservec1_enable.integer)
866 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
867 if (r_glsl_postprocess_uservec2_enable.integer)
868 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
869 if (r_glsl_postprocess_uservec3_enable.integer)
870 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
871 if (r_glsl_postprocess_uservec4_enable.integer)
872 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
874 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
877 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
878 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
879 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
881 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
882 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
884 shaderstaticparms_count = 0;
887 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
888 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
889 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
890 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
891 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
892 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
895 /// information about each possible shader permutation
896 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
897 /// currently selected permutation
898 r_glsl_permutation_t *r_glsl_permutation;
899 /// storage for permutations linked in the hash table
900 memexpandablearray_t r_glsl_permutationarray;
902 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
904 //unsigned int hashdepth = 0;
905 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
906 r_glsl_permutation_t *p;
907 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
909 if (p->mode == mode && p->permutation == permutation)
911 //if (hashdepth > 10)
912 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
917 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
919 p->permutation = permutation;
920 p->hashnext = r_glsl_permutationhash[mode][hashindex];
921 r_glsl_permutationhash[mode][hashindex] = p;
922 //if (hashdepth > 10)
923 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
927 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
930 if (!filename || !filename[0])
932 if (!strcmp(filename, "glsl/default.glsl"))
934 if (!glslshaderstring)
936 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
937 if (glslshaderstring)
938 Con_DPrintf("Loading shaders from file %s...\n", filename);
940 glslshaderstring = (char *)builtinshaderstring;
942 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
943 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
946 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
949 if (printfromdisknotice)
950 Con_DPrintf("from disk %s... ", filename);
956 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
960 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
961 char *vertexstring, *geometrystring, *fragmentstring;
962 char permutationname[256];
963 int vertstrings_count = 0;
964 int geomstrings_count = 0;
965 int fragstrings_count = 0;
966 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
967 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
968 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
975 permutationname[0] = 0;
976 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
977 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
978 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
980 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
982 // the first pretext is which type of shader to compile as
983 // (later these will all be bound together as a program object)
984 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
985 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
986 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
988 // the second pretext is the mode (for example a light source)
989 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
990 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
991 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
992 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
994 // now add all the permutation pretexts
995 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
997 if (permutation & (1<<i))
999 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1000 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1001 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1002 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1006 // keep line numbers correct
1007 vertstrings_list[vertstrings_count++] = "\n";
1008 geomstrings_list[geomstrings_count++] = "\n";
1009 fragstrings_list[fragstrings_count++] = "\n";
1014 R_CompileShader_AddStaticParms(mode, permutation);
1015 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1016 vertstrings_count += shaderstaticparms_count;
1017 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1018 geomstrings_count += shaderstaticparms_count;
1019 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1020 fragstrings_count += shaderstaticparms_count;
1022 // now append the shader text itself
1023 vertstrings_list[vertstrings_count++] = vertexstring;
1024 geomstrings_list[geomstrings_count++] = geometrystring;
1025 fragstrings_list[fragstrings_count++] = fragmentstring;
1027 // if any sources were NULL, clear the respective list
1029 vertstrings_count = 0;
1030 if (!geometrystring)
1031 geomstrings_count = 0;
1032 if (!fragmentstring)
1033 fragstrings_count = 0;
1035 // compile the shader program
1036 if (vertstrings_count + geomstrings_count + fragstrings_count)
1037 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1041 qglUseProgram(p->program);CHECKGLERROR
1042 // look up all the uniform variable names we care about, so we don't
1043 // have to look them up every time we set them
1045 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1046 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1047 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1048 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1049 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1050 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1051 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1052 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1053 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1054 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1055 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1056 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1057 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1058 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1059 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1060 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1061 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1062 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1063 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1064 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1065 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1066 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1067 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1068 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1069 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1070 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1071 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1072 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1073 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1074 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1075 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1076 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1077 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1078 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1079 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1080 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1081 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1082 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1083 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1084 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1085 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1086 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1087 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1088 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1089 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1090 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1091 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1092 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1093 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1094 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1095 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1096 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1097 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1098 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1099 p->loc_OffsetMapping_Scale = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
1100 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1101 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1102 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1103 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1104 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1105 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1106 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1107 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1108 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1109 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1110 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1111 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1112 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1113 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1114 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1115 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1116 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1117 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1118 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1119 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1120 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1121 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1122 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1123 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1124 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1125 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1126 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1127 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1128 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1129 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1130 // initialize the samplers to refer to the texture units we use
1131 p->tex_Texture_First = -1;
1132 p->tex_Texture_Second = -1;
1133 p->tex_Texture_GammaRamps = -1;
1134 p->tex_Texture_Normal = -1;
1135 p->tex_Texture_Color = -1;
1136 p->tex_Texture_Gloss = -1;
1137 p->tex_Texture_Glow = -1;
1138 p->tex_Texture_SecondaryNormal = -1;
1139 p->tex_Texture_SecondaryColor = -1;
1140 p->tex_Texture_SecondaryGloss = -1;
1141 p->tex_Texture_SecondaryGlow = -1;
1142 p->tex_Texture_Pants = -1;
1143 p->tex_Texture_Shirt = -1;
1144 p->tex_Texture_FogHeightTexture = -1;
1145 p->tex_Texture_FogMask = -1;
1146 p->tex_Texture_Lightmap = -1;
1147 p->tex_Texture_Deluxemap = -1;
1148 p->tex_Texture_Attenuation = -1;
1149 p->tex_Texture_Cube = -1;
1150 p->tex_Texture_Refraction = -1;
1151 p->tex_Texture_Reflection = -1;
1152 p->tex_Texture_ShadowMap2D = -1;
1153 p->tex_Texture_CubeProjection = -1;
1154 p->tex_Texture_ScreenDepth = -1;
1155 p->tex_Texture_ScreenNormalMap = -1;
1156 p->tex_Texture_ScreenDiffuse = -1;
1157 p->tex_Texture_ScreenSpecular = -1;
1158 p->tex_Texture_ReflectMask = -1;
1159 p->tex_Texture_ReflectCube = -1;
1160 p->tex_Texture_BounceGrid = -1;
1162 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1163 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1164 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1165 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1166 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1167 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1168 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1169 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1170 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1171 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1172 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1173 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1174 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1175 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1176 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1177 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1178 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1179 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1180 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1181 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1182 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1183 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1184 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1185 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1186 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1187 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1188 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1189 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1190 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1191 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1193 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1196 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1200 Mem_Free(vertexstring);
1202 Mem_Free(geometrystring);
1204 Mem_Free(fragmentstring);
1207 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1209 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1210 if (r_glsl_permutation != perm)
1212 r_glsl_permutation = perm;
1213 if (!r_glsl_permutation->program)
1215 if (!r_glsl_permutation->compiled)
1216 R_GLSL_CompilePermutation(perm, mode, permutation);
1217 if (!r_glsl_permutation->program)
1219 // remove features until we find a valid permutation
1221 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1223 // reduce i more quickly whenever it would not remove any bits
1224 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1225 if (!(permutation & j))
1228 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1229 if (!r_glsl_permutation->compiled)
1230 R_GLSL_CompilePermutation(perm, mode, permutation);
1231 if (r_glsl_permutation->program)
1234 if (i >= SHADERPERMUTATION_COUNT)
1236 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1237 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1238 qglUseProgram(0);CHECKGLERROR
1239 return; // no bit left to clear, entire mode is broken
1244 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1246 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1247 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1248 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1255 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1256 extern D3DCAPS9 vid_d3d9caps;
1259 struct r_hlsl_permutation_s;
1260 typedef struct r_hlsl_permutation_s
1262 /// hash lookup data
1263 struct r_hlsl_permutation_s *hashnext;
1265 unsigned int permutation;
1267 /// indicates if we have tried compiling this permutation already
1269 /// NULL if compilation failed
1270 IDirect3DVertexShader9 *vertexshader;
1271 IDirect3DPixelShader9 *pixelshader;
1273 r_hlsl_permutation_t;
1275 typedef enum D3DVSREGISTER_e
1277 D3DVSREGISTER_TexMatrix = 0, // float4x4
1278 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1279 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1280 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1281 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1282 D3DVSREGISTER_ModelToLight = 20, // float4x4
1283 D3DVSREGISTER_EyePosition = 24,
1284 D3DVSREGISTER_FogPlane = 25,
1285 D3DVSREGISTER_LightDir = 26,
1286 D3DVSREGISTER_LightPosition = 27,
1290 typedef enum D3DPSREGISTER_e
1292 D3DPSREGISTER_Alpha = 0,
1293 D3DPSREGISTER_BloomBlur_Parameters = 1,
1294 D3DPSREGISTER_ClientTime = 2,
1295 D3DPSREGISTER_Color_Ambient = 3,
1296 D3DPSREGISTER_Color_Diffuse = 4,
1297 D3DPSREGISTER_Color_Specular = 5,
1298 D3DPSREGISTER_Color_Glow = 6,
1299 D3DPSREGISTER_Color_Pants = 7,
1300 D3DPSREGISTER_Color_Shirt = 8,
1301 D3DPSREGISTER_DeferredColor_Ambient = 9,
1302 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1303 D3DPSREGISTER_DeferredColor_Specular = 11,
1304 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1305 D3DPSREGISTER_DeferredMod_Specular = 13,
1306 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1307 D3DPSREGISTER_EyePosition = 15, // unused
1308 D3DPSREGISTER_FogColor = 16,
1309 D3DPSREGISTER_FogHeightFade = 17,
1310 D3DPSREGISTER_FogPlane = 18,
1311 D3DPSREGISTER_FogPlaneViewDist = 19,
1312 D3DPSREGISTER_FogRangeRecip = 20,
1313 D3DPSREGISTER_LightColor = 21,
1314 D3DPSREGISTER_LightDir = 22, // unused
1315 D3DPSREGISTER_LightPosition = 23,
1316 D3DPSREGISTER_OffsetMapping_Scale = 24,
1317 D3DPSREGISTER_PixelSize = 25,
1318 D3DPSREGISTER_ReflectColor = 26,
1319 D3DPSREGISTER_ReflectFactor = 27,
1320 D3DPSREGISTER_ReflectOffset = 28,
1321 D3DPSREGISTER_RefractColor = 29,
1322 D3DPSREGISTER_Saturation = 30,
1323 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1324 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1325 D3DPSREGISTER_ScreenToDepth = 33,
1326 D3DPSREGISTER_ShadowMap_Parameters = 34,
1327 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1328 D3DPSREGISTER_SpecularPower = 36,
1329 D3DPSREGISTER_UserVec1 = 37,
1330 D3DPSREGISTER_UserVec2 = 38,
1331 D3DPSREGISTER_UserVec3 = 39,
1332 D3DPSREGISTER_UserVec4 = 40,
1333 D3DPSREGISTER_ViewTintColor = 41,
1334 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1335 D3DPSREGISTER_BloomColorSubtract = 43,
1336 D3DPSREGISTER_ViewToLight = 44, // float4x4
1337 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1338 D3DPSREGISTER_NormalmapScrollBlend = 52,
1343 /// information about each possible shader permutation
1344 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1345 /// currently selected permutation
1346 r_hlsl_permutation_t *r_hlsl_permutation;
1347 /// storage for permutations linked in the hash table
1348 memexpandablearray_t r_hlsl_permutationarray;
1350 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1352 //unsigned int hashdepth = 0;
1353 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1354 r_hlsl_permutation_t *p;
1355 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1357 if (p->mode == mode && p->permutation == permutation)
1359 //if (hashdepth > 10)
1360 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1365 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1367 p->permutation = permutation;
1368 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1369 r_hlsl_permutationhash[mode][hashindex] = p;
1370 //if (hashdepth > 10)
1371 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1375 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1378 if (!filename || !filename[0])
1380 if (!strcmp(filename, "hlsl/default.hlsl"))
1382 if (!hlslshaderstring)
1384 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1385 if (hlslshaderstring)
1386 Con_DPrintf("Loading shaders from file %s...\n", filename);
1388 hlslshaderstring = (char *)builtinhlslshaderstring;
1390 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1391 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1392 return shaderstring;
1394 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1397 if (printfromdisknotice)
1398 Con_DPrintf("from disk %s... ", filename);
1399 return shaderstring;
1401 return shaderstring;
1405 //#include <d3dx9shader.h>
1406 //#include <d3dx9mesh.h>
1408 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1410 DWORD *vsbin = NULL;
1411 DWORD *psbin = NULL;
1412 fs_offset_t vsbinsize;
1413 fs_offset_t psbinsize;
1414 // IDirect3DVertexShader9 *vs = NULL;
1415 // IDirect3DPixelShader9 *ps = NULL;
1416 ID3DXBuffer *vslog = NULL;
1417 ID3DXBuffer *vsbuffer = NULL;
1418 ID3DXConstantTable *vsconstanttable = NULL;
1419 ID3DXBuffer *pslog = NULL;
1420 ID3DXBuffer *psbuffer = NULL;
1421 ID3DXConstantTable *psconstanttable = NULL;
1424 char temp[MAX_INPUTLINE];
1425 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1426 qboolean debugshader = gl_paranoid.integer != 0;
1427 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1428 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1431 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1432 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1434 if ((!vsbin && vertstring) || (!psbin && fragstring))
1436 const char* dllnames_d3dx9 [] =
1460 dllhandle_t d3dx9_dll = NULL;
1461 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1462 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1463 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1464 dllfunction_t d3dx9_dllfuncs[] =
1466 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1467 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1468 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1471 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1473 DWORD shaderflags = 0;
1475 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1476 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1477 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1478 if (vertstring && vertstring[0])
1482 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1483 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1484 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1485 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1488 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1491 vsbinsize = vsbuffer->GetBufferSize();
1492 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1493 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1494 vsbuffer->Release();
1498 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1499 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1503 if (fragstring && fragstring[0])
1507 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1508 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1509 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1510 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1513 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1516 psbinsize = psbuffer->GetBufferSize();
1517 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1518 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1519 psbuffer->Release();
1523 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1524 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1528 Sys_UnloadLibrary(&d3dx9_dll);
1531 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1535 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1536 if (FAILED(vsresult))
1537 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1538 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1539 if (FAILED(psresult))
1540 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1542 // free the shader data
1543 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1544 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1547 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1550 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1551 int vertstring_length = 0;
1552 int geomstring_length = 0;
1553 int fragstring_length = 0;
1555 char *vertexstring, *geometrystring, *fragmentstring;
1556 char *vertstring, *geomstring, *fragstring;
1557 char permutationname[256];
1558 char cachename[256];
1559 int vertstrings_count = 0;
1560 int geomstrings_count = 0;
1561 int fragstrings_count = 0;
1562 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1563 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1564 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1569 p->vertexshader = NULL;
1570 p->pixelshader = NULL;
1572 permutationname[0] = 0;
1574 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1575 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1576 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1578 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1579 strlcat(cachename, "hlsl/", sizeof(cachename));
1581 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1582 vertstrings_count = 0;
1583 geomstrings_count = 0;
1584 fragstrings_count = 0;
1585 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1586 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1587 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1589 // the first pretext is which type of shader to compile as
1590 // (later these will all be bound together as a program object)
1591 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1592 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1593 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1595 // the second pretext is the mode (for example a light source)
1596 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1597 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1598 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1599 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1600 strlcat(cachename, modeinfo->name, sizeof(cachename));
1602 // now add all the permutation pretexts
1603 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1605 if (permutation & (1<<i))
1607 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1608 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1609 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1610 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1611 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1615 // keep line numbers correct
1616 vertstrings_list[vertstrings_count++] = "\n";
1617 geomstrings_list[geomstrings_count++] = "\n";
1618 fragstrings_list[fragstrings_count++] = "\n";
1623 R_CompileShader_AddStaticParms(mode, permutation);
1624 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1625 vertstrings_count += shaderstaticparms_count;
1626 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1627 geomstrings_count += shaderstaticparms_count;
1628 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1629 fragstrings_count += shaderstaticparms_count;
1631 // replace spaces in the cachename with _ characters
1632 for (i = 0;cachename[i];i++)
1633 if (cachename[i] == ' ')
1636 // now append the shader text itself
1637 vertstrings_list[vertstrings_count++] = vertexstring;
1638 geomstrings_list[geomstrings_count++] = geometrystring;
1639 fragstrings_list[fragstrings_count++] = fragmentstring;
1641 // if any sources were NULL, clear the respective list
1643 vertstrings_count = 0;
1644 if (!geometrystring)
1645 geomstrings_count = 0;
1646 if (!fragmentstring)
1647 fragstrings_count = 0;
1649 vertstring_length = 0;
1650 for (i = 0;i < vertstrings_count;i++)
1651 vertstring_length += strlen(vertstrings_list[i]);
1652 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1653 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1654 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1656 geomstring_length = 0;
1657 for (i = 0;i < geomstrings_count;i++)
1658 geomstring_length += strlen(geomstrings_list[i]);
1659 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1660 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1661 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1663 fragstring_length = 0;
1664 for (i = 0;i < fragstrings_count;i++)
1665 fragstring_length += strlen(fragstrings_list[i]);
1666 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1667 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1668 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1670 // try to load the cached shader, or generate one
1671 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1673 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1674 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1676 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1680 Mem_Free(vertstring);
1682 Mem_Free(geomstring);
1684 Mem_Free(fragstring);
1686 Mem_Free(vertexstring);
1688 Mem_Free(geometrystring);
1690 Mem_Free(fragmentstring);
1693 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1694 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1695 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);}
1696 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);}
1697 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);}
1698 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);}
1700 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1701 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1702 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);}
1703 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);}
1704 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);}
1705 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);}
1707 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1709 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1710 if (r_hlsl_permutation != perm)
1712 r_hlsl_permutation = perm;
1713 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1715 if (!r_hlsl_permutation->compiled)
1716 R_HLSL_CompilePermutation(perm, mode, permutation);
1717 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1719 // remove features until we find a valid permutation
1721 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1723 // reduce i more quickly whenever it would not remove any bits
1724 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1725 if (!(permutation & j))
1728 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1729 if (!r_hlsl_permutation->compiled)
1730 R_HLSL_CompilePermutation(perm, mode, permutation);
1731 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1734 if (i >= SHADERPERMUTATION_COUNT)
1736 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1737 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1738 return; // no bit left to clear, entire mode is broken
1742 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1743 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1745 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1746 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1747 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1751 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1753 DPSOFTRAST_SetShader(mode, permutation);
1754 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1755 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1756 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1759 void R_GLSL_Restart_f(void)
1761 unsigned int i, limit;
1762 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1763 Mem_Free(glslshaderstring);
1764 glslshaderstring = NULL;
1765 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1766 Mem_Free(hlslshaderstring);
1767 hlslshaderstring = NULL;
1768 switch(vid.renderpath)
1770 case RENDERPATH_D3D9:
1773 r_hlsl_permutation_t *p;
1774 r_hlsl_permutation = NULL;
1775 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1776 for (i = 0;i < limit;i++)
1778 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1780 if (p->vertexshader)
1781 IDirect3DVertexShader9_Release(p->vertexshader);
1783 IDirect3DPixelShader9_Release(p->pixelshader);
1784 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1787 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1791 case RENDERPATH_D3D10:
1792 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1794 case RENDERPATH_D3D11:
1795 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1797 case RENDERPATH_GL20:
1798 case RENDERPATH_GLES2:
1800 r_glsl_permutation_t *p;
1801 r_glsl_permutation = NULL;
1802 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1803 for (i = 0;i < limit;i++)
1805 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1807 GL_Backend_FreeProgram(p->program);
1808 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1811 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1814 case RENDERPATH_GL13:
1815 case RENDERPATH_GL11:
1817 case RENDERPATH_SOFT:
1822 void R_GLSL_DumpShader_f(void)
1827 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1830 FS_Print(file, "/* The engine may define the following macros:\n");
1831 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1832 for (i = 0;i < SHADERMODE_COUNT;i++)
1833 FS_Print(file, glslshadermodeinfo[i].pretext);
1834 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1835 FS_Print(file, shaderpermutationinfo[i].pretext);
1836 FS_Print(file, "*/\n");
1837 FS_Print(file, builtinshaderstring);
1839 Con_Printf("glsl/default.glsl written\n");
1842 Con_Printf("failed to write to glsl/default.glsl\n");
1844 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1847 FS_Print(file, "/* The engine may define the following macros:\n");
1848 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1849 for (i = 0;i < SHADERMODE_COUNT;i++)
1850 FS_Print(file, hlslshadermodeinfo[i].pretext);
1851 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1852 FS_Print(file, shaderpermutationinfo[i].pretext);
1853 FS_Print(file, "*/\n");
1854 FS_Print(file, builtinhlslshaderstring);
1856 Con_Printf("hlsl/default.hlsl written\n");
1859 Con_Printf("failed to write to hlsl/default.hlsl\n");
1862 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1865 texturemode = GL_MODULATE;
1866 switch (vid.renderpath)
1868 case RENDERPATH_D3D9:
1870 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))));
1871 R_Mesh_TexBind(GL20TU_FIRST , first );
1872 R_Mesh_TexBind(GL20TU_SECOND, second);
1875 case RENDERPATH_D3D10:
1876 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1878 case RENDERPATH_D3D11:
1879 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1881 case RENDERPATH_GL20:
1882 case RENDERPATH_GLES2:
1883 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))));
1884 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1885 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1887 case RENDERPATH_GL13:
1888 R_Mesh_TexBind(0, first );
1889 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1890 R_Mesh_TexBind(1, second);
1892 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1894 case RENDERPATH_GL11:
1895 R_Mesh_TexBind(0, first );
1897 case RENDERPATH_SOFT:
1898 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))));
1899 R_Mesh_TexBind(GL20TU_FIRST , first );
1900 R_Mesh_TexBind(GL20TU_SECOND, second);
1905 void R_SetupShader_DepthOrShadow(void)
1907 switch (vid.renderpath)
1909 case RENDERPATH_D3D9:
1911 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1914 case RENDERPATH_D3D10:
1915 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1917 case RENDERPATH_D3D11:
1918 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1920 case RENDERPATH_GL20:
1921 case RENDERPATH_GLES2:
1922 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1924 case RENDERPATH_GL13:
1925 R_Mesh_TexBind(0, 0);
1926 R_Mesh_TexBind(1, 0);
1928 case RENDERPATH_GL11:
1929 R_Mesh_TexBind(0, 0);
1931 case RENDERPATH_SOFT:
1932 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1937 void R_SetupShader_ShowDepth(void)
1939 switch (vid.renderpath)
1941 case RENDERPATH_D3D9:
1943 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1946 case RENDERPATH_D3D10:
1947 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1949 case RENDERPATH_D3D11:
1950 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1952 case RENDERPATH_GL20:
1953 case RENDERPATH_GLES2:
1954 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1956 case RENDERPATH_GL13:
1958 case RENDERPATH_GL11:
1960 case RENDERPATH_SOFT:
1961 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1966 extern qboolean r_shadow_usingdeferredprepass;
1967 extern cvar_t r_shadow_deferred_8bitrange;
1968 extern rtexture_t *r_shadow_attenuationgradienttexture;
1969 extern rtexture_t *r_shadow_attenuation2dtexture;
1970 extern rtexture_t *r_shadow_attenuation3dtexture;
1971 extern qboolean r_shadow_usingshadowmap2d;
1972 extern qboolean r_shadow_usingshadowmaportho;
1973 extern float r_shadow_shadowmap_texturescale[2];
1974 extern float r_shadow_shadowmap_parameters[4];
1975 extern qboolean r_shadow_shadowmapvsdct;
1976 extern qboolean r_shadow_shadowmapsampler;
1977 extern int r_shadow_shadowmappcf;
1978 extern rtexture_t *r_shadow_shadowmap2dtexture;
1979 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1980 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1981 extern matrix4x4_t r_shadow_shadowmapmatrix;
1982 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1983 extern int r_shadow_prepass_width;
1984 extern int r_shadow_prepass_height;
1985 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1986 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1987 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
1988 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
1989 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
1990 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
1992 // a blendfunc allows colormod if:
1993 // a) it can never keep the destination pixel invariant, or
1994 // b) it can keep the destination pixel invariant, and still can do so if colormodded
1995 // this is to prevent unintended side effects from colormod
1998 // IF there is a (s, sa) for which for all (d, da),
1999 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
2000 // THEN, for this (s, sa) and all (colormod, d, da):
2001 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
2002 // OBVIOUSLY, this means that
2003 // s*colormod * src(s*colormod, d, sa, da) = 0
2004 // dst(s*colormod, d, sa, da) = 1
2006 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
2008 // main condition to leave dst color invariant:
2009 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
2011 // s * 0 + d * dst(s, d, sa, da) == d
2012 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2013 // => colormod is a problem for GL_SRC_COLOR only
2015 // s + d * dst(s, d, sa, da) == d
2017 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2018 // => colormod is never problematic for these
2019 // src == GL_SRC_COLOR:
2020 // s*s + d * dst(s, d, sa, da) == d
2022 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2023 // => colormod is never problematic for these
2024 // src == GL_ONE_MINUS_SRC_COLOR:
2025 // s*(1-s) + d * dst(s, d, sa, da) == d
2026 // => s == 0 or s == 1
2027 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2028 // => colormod is a problem for GL_SRC_COLOR only
2029 // src == GL_DST_COLOR
2030 // s*d + d * dst(s, d, sa, da) == d
2032 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2033 // => colormod is always a problem
2036 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2037 // => colormod is never problematic for these
2038 // => BUT, we do not know s! We must assume it is problematic
2039 // then... except in GL_ONE case, where we know all invariant
2041 // src == GL_ONE_MINUS_DST_COLOR
2042 // s*(1-d) + d * dst(s, d, sa, da) == d
2043 // => s == 0 (1-d is impossible to handle for our desired result)
2044 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2045 // => colormod is never problematic for these
2046 // src == GL_SRC_ALPHA
2047 // s*sa + d * dst(s, d, sa, da) == d
2048 // => s == 0, or sa == 0
2049 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2050 // => colormod breaks in the case GL_SRC_COLOR only
2051 // src == GL_ONE_MINUS_SRC_ALPHA
2052 // s*(1-sa) + d * dst(s, d, sa, da) == d
2053 // => s == 0, or sa == 1
2054 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2055 // => colormod breaks in the case GL_SRC_COLOR only
2056 // src == GL_DST_ALPHA
2057 // s*da + d * dst(s, d, sa, da) == d
2059 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2060 // => colormod is never problematic for these
2065 case GL_ONE_MINUS_SRC_COLOR:
2067 case GL_ONE_MINUS_SRC_ALPHA:
2068 if(dst == GL_SRC_COLOR)
2073 case GL_ONE_MINUS_DST_COLOR:
2075 case GL_ONE_MINUS_DST_ALPHA:
2085 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)
2087 // select a permutation of the lighting shader appropriate to this
2088 // combination of texture, entity, light source, and fogging, only use the
2089 // minimum features necessary to avoid wasting rendering time in the
2090 // fragment shader on features that are not being used
2091 unsigned int permutation = 0;
2092 unsigned int mode = 0;
2093 qboolean allow_colormod;
2094 static float dummy_colormod[3] = {1, 1, 1};
2095 float *colormod = rsurface.colormod;
2097 matrix4x4_t tempmatrix;
2098 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2099 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2100 permutation |= SHADERPERMUTATION_ALPHAKILL;
2101 if (rsurfacepass == RSURFPASS_BACKGROUND)
2103 // distorted background
2104 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2106 mode = SHADERMODE_WATER;
2107 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2108 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2109 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2111 // this is the right thing to do for wateralpha
2112 GL_BlendFunc(GL_ONE, GL_ZERO);
2113 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
2117 // this is the right thing to do for entity alpha
2118 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2119 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2122 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2124 mode = SHADERMODE_REFRACTION;
2125 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2126 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2130 mode = SHADERMODE_GENERIC;
2131 permutation |= SHADERPERMUTATION_DIFFUSE;
2132 GL_BlendFunc(GL_ONE, GL_ZERO);
2133 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
2136 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2138 if (r_glsl_offsetmapping.integer)
2140 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2141 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2142 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2143 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2144 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2146 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2147 if (r_glsl_offsetmapping_reliefmapping.integer)
2148 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2151 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2152 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2153 // normalmap (deferred prepass), may use alpha test on diffuse
2154 mode = SHADERMODE_DEFERREDGEOMETRY;
2155 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2156 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2157 GL_BlendFunc(GL_ONE, GL_ZERO);
2158 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
2160 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2162 if (r_glsl_offsetmapping.integer)
2164 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2165 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2166 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2167 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2168 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2170 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2171 if (r_glsl_offsetmapping_reliefmapping.integer)
2172 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2175 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2176 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2178 mode = SHADERMODE_LIGHTSOURCE;
2179 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2180 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2181 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2182 permutation |= SHADERPERMUTATION_CUBEFILTER;
2183 if (diffusescale > 0)
2184 permutation |= SHADERPERMUTATION_DIFFUSE;
2185 if (specularscale > 0)
2186 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2187 if (r_refdef.fogenabled)
2188 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2189 if (rsurface.texture->colormapping)
2190 permutation |= SHADERPERMUTATION_COLORMAPPING;
2191 if (r_shadow_usingshadowmap2d)
2193 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2194 if(r_shadow_shadowmapvsdct)
2195 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2197 if (r_shadow_shadowmapsampler)
2198 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2199 if (r_shadow_shadowmappcf > 1)
2200 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2201 else if (r_shadow_shadowmappcf)
2202 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2204 if (rsurface.texture->reflectmasktexture)
2205 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2206 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2207 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
2209 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2211 if (r_glsl_offsetmapping.integer)
2213 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2214 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2215 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2216 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2217 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2219 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2220 if (r_glsl_offsetmapping_reliefmapping.integer)
2221 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2224 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2225 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2226 // unshaded geometry (fullbright or ambient model lighting)
2227 mode = SHADERMODE_FLATCOLOR;
2228 ambientscale = diffusescale = specularscale = 0;
2229 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2230 permutation |= SHADERPERMUTATION_GLOW;
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 (rsurface.texture->reflectmasktexture)
2250 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2251 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2252 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2254 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2256 if (r_glsl_offsetmapping.integer)
2258 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2259 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2260 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2261 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2262 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2264 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2265 if (r_glsl_offsetmapping_reliefmapping.integer)
2266 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2269 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2270 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2271 // directional model lighting
2272 mode = SHADERMODE_LIGHTDIRECTION;
2273 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2274 permutation |= SHADERPERMUTATION_GLOW;
2275 permutation |= SHADERPERMUTATION_DIFFUSE;
2276 if (specularscale > 0)
2277 permutation |= SHADERPERMUTATION_SPECULAR;
2278 if (r_refdef.fogenabled)
2279 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2280 if (rsurface.texture->colormapping)
2281 permutation |= SHADERPERMUTATION_COLORMAPPING;
2282 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2284 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2285 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2287 if (r_shadow_shadowmapsampler)
2288 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2289 if (r_shadow_shadowmappcf > 1)
2290 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2291 else if (r_shadow_shadowmappcf)
2292 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2294 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2295 permutation |= SHADERPERMUTATION_REFLECTION;
2296 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2297 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2298 if (rsurface.texture->reflectmasktexture)
2299 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2300 if (r_shadow_bouncegridtexture)
2301 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2302 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2303 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2305 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2307 if (r_glsl_offsetmapping.integer)
2309 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2310 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2311 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2312 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2313 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2315 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2316 if (r_glsl_offsetmapping_reliefmapping.integer)
2317 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2320 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2321 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2322 // ambient model lighting
2323 mode = SHADERMODE_LIGHTDIRECTION;
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 (r_shadow_bouncegridtexture)
2349 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2350 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2351 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2355 if (r_glsl_offsetmapping.integer)
2357 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2358 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2359 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2360 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2361 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2363 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2364 if (r_glsl_offsetmapping_reliefmapping.integer)
2365 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2368 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2369 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2371 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2372 permutation |= SHADERPERMUTATION_GLOW;
2373 if (r_refdef.fogenabled)
2374 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2375 if (rsurface.texture->colormapping)
2376 permutation |= SHADERPERMUTATION_COLORMAPPING;
2377 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2379 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2380 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2382 if (r_shadow_shadowmapsampler)
2383 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2384 if (r_shadow_shadowmappcf > 1)
2385 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2386 else if (r_shadow_shadowmappcf)
2387 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2389 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2390 permutation |= SHADERPERMUTATION_REFLECTION;
2391 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2392 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2393 if (rsurface.texture->reflectmasktexture)
2394 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2395 if (FAKELIGHT_ENABLED)
2397 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2398 mode = SHADERMODE_FAKELIGHT;
2399 permutation |= SHADERPERMUTATION_DIFFUSE;
2400 if (specularscale > 0)
2401 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2403 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2405 // deluxemapping (light direction texture)
2406 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2407 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2409 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2410 permutation |= SHADERPERMUTATION_DIFFUSE;
2411 if (specularscale > 0)
2412 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2414 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2416 // fake deluxemapping (uniform light direction in tangentspace)
2417 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2418 permutation |= SHADERPERMUTATION_DIFFUSE;
2419 if (specularscale > 0)
2420 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2422 else if (rsurface.uselightmaptexture)
2424 // ordinary lightmapping (q1bsp, q3bsp)
2425 mode = SHADERMODE_LIGHTMAP;
2429 // ordinary vertex coloring (q3bsp)
2430 mode = SHADERMODE_VERTEXCOLOR;
2432 if (r_shadow_bouncegridtexture)
2433 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2434 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2435 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2438 colormod = dummy_colormod;
2439 switch(vid.renderpath)
2441 case RENDERPATH_D3D9:
2443 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);
2444 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2445 R_SetupShader_SetPermutationHLSL(mode, permutation);
2446 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2447 if (mode == SHADERMODE_LIGHTSOURCE)
2449 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2450 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2454 if (mode == SHADERMODE_LIGHTDIRECTION)
2456 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2459 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2460 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2461 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2462 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2463 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2465 if (mode == SHADERMODE_LIGHTSOURCE)
2467 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2468 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2469 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2470 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2471 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2473 // additive passes are only darkened by fog, not tinted
2474 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2475 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2479 if (mode == SHADERMODE_FLATCOLOR)
2481 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2483 else if (mode == SHADERMODE_LIGHTDIRECTION)
2485 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]);
2486 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2487 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);
2488 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);
2489 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2490 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2491 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2495 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2496 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2497 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);
2498 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);
2499 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2501 // additive passes are only darkened by fog, not tinted
2502 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2503 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2505 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2506 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);
2507 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2508 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2509 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2510 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2511 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2512 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2513 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2514 if (mode == SHADERMODE_WATER)
2515 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2517 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2518 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2519 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2520 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));
2521 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2522 if (rsurface.texture->pantstexture)
2523 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2525 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2526 if (rsurface.texture->shirttexture)
2527 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2529 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2530 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2531 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2532 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2533 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2534 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2535 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2536 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2538 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2539 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2540 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2541 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2542 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2543 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2544 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2545 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2546 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2547 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2548 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2549 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2550 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2551 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2552 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2553 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2554 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2555 if (rsurfacepass == RSURFPASS_BACKGROUND)
2557 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2558 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2559 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2563 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2565 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2566 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2567 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2568 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2569 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2571 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2572 if (rsurface.rtlight)
2574 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2575 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2580 case RENDERPATH_D3D10:
2581 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2583 case RENDERPATH_D3D11:
2584 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2586 case RENDERPATH_GL20:
2587 case RENDERPATH_GLES2:
2588 if (!vid.useinterleavedarrays)
2590 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);
2591 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2592 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2593 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2594 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2595 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2596 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2597 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2601 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);
2602 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2604 R_SetupShader_SetPermutationGLSL(mode, permutation);
2605 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2606 if (mode == SHADERMODE_LIGHTSOURCE)
2608 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2609 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2610 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2611 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2612 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2613 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);
2615 // additive passes are only darkened by fog, not tinted
2616 if (r_glsl_permutation->loc_FogColor >= 0)
2617 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2618 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2622 if (mode == SHADERMODE_FLATCOLOR)
2624 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2626 else if (mode == SHADERMODE_LIGHTDIRECTION)
2628 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]);
2629 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]);
2630 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);
2631 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);
2632 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);
2633 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]);
2634 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]);
2638 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]);
2639 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]);
2640 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);
2641 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);
2642 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);
2644 // additive passes are only darkened by fog, not tinted
2645 if (r_glsl_permutation->loc_FogColor >= 0)
2647 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2648 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2650 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2652 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);
2653 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]);
2654 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]);
2655 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]);
2656 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]);
2657 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2658 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2659 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2660 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]);
2662 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2663 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2664 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2665 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]);
2666 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]);
2668 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2669 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));
2670 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2671 if (r_glsl_permutation->loc_Color_Pants >= 0)
2673 if (rsurface.texture->pantstexture)
2674 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2676 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2678 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2680 if (rsurface.texture->shirttexture)
2681 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2683 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2685 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]);
2686 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2687 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2688 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2689 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2690 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]);
2691 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2692 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);}
2693 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2695 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2696 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2697 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2698 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2699 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2700 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2701 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2702 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2703 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2704 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2705 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2706 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2707 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2708 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2709 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);
2710 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2711 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2712 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2713 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2714 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2715 if (rsurfacepass == RSURFPASS_BACKGROUND)
2717 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);
2718 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);
2719 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);
2723 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);
2725 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2726 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2727 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2728 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2729 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2731 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2732 if (rsurface.rtlight)
2734 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2735 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2738 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2741 case RENDERPATH_GL13:
2742 case RENDERPATH_GL11:
2744 case RENDERPATH_SOFT:
2745 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);
2746 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2747 R_SetupShader_SetPermutationSoft(mode, permutation);
2748 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2749 if (mode == SHADERMODE_LIGHTSOURCE)
2751 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2752 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2753 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2754 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2755 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2756 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2758 // additive passes are only darkened by fog, not tinted
2759 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2760 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2764 if (mode == SHADERMODE_FLATCOLOR)
2766 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2768 else if (mode == SHADERMODE_LIGHTDIRECTION)
2770 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]);
2771 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2772 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);
2773 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);
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2775 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]);
2776 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2780 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2781 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2782 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);
2783 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);
2784 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2786 // additive passes are only darkened by fog, not tinted
2787 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2788 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2790 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2791 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);
2792 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2793 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2794 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]);
2795 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]);
2796 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2797 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2798 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2799 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2801 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2802 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2803 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2804 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2805 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]);
2807 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2808 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));
2809 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2810 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2812 if (rsurface.texture->pantstexture)
2813 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2815 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2817 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2819 if (rsurface.texture->shirttexture)
2820 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2822 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2824 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2825 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2826 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2827 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2828 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2829 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2830 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2832 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2833 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2834 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2835 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2836 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2837 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2838 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2839 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2840 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2841 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2842 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2843 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2844 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2845 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2846 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2847 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2848 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2849 if (rsurfacepass == RSURFPASS_BACKGROUND)
2851 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2852 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2853 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2857 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2859 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2860 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2861 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2862 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2863 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2865 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2866 if (rsurface.rtlight)
2868 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2869 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2876 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2878 // select a permutation of the lighting shader appropriate to this
2879 // combination of texture, entity, light source, and fogging, only use the
2880 // minimum features necessary to avoid wasting rendering time in the
2881 // fragment shader on features that are not being used
2882 unsigned int permutation = 0;
2883 unsigned int mode = 0;
2884 const float *lightcolorbase = rtlight->currentcolor;
2885 float ambientscale = rtlight->ambientscale;
2886 float diffusescale = rtlight->diffusescale;
2887 float specularscale = rtlight->specularscale;
2888 // this is the location of the light in view space
2889 vec3_t viewlightorigin;
2890 // this transforms from view space (camera) to light space (cubemap)
2891 matrix4x4_t viewtolight;
2892 matrix4x4_t lighttoview;
2893 float viewtolight16f[16];
2894 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2896 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2897 if (rtlight->currentcubemap != r_texture_whitecube)
2898 permutation |= SHADERPERMUTATION_CUBEFILTER;
2899 if (diffusescale > 0)
2900 permutation |= SHADERPERMUTATION_DIFFUSE;
2901 if (specularscale > 0)
2902 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2903 if (r_shadow_usingshadowmap2d)
2905 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2906 if (r_shadow_shadowmapvsdct)
2907 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2909 if (r_shadow_shadowmapsampler)
2910 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2911 if (r_shadow_shadowmappcf > 1)
2912 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2913 else if (r_shadow_shadowmappcf)
2914 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2916 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2917 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2918 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2919 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2920 switch(vid.renderpath)
2922 case RENDERPATH_D3D9:
2924 R_SetupShader_SetPermutationHLSL(mode, permutation);
2925 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2926 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2927 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2928 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2929 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2930 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2931 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2932 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2933 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2934 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2936 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2937 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2938 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2939 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2940 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2941 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2944 case RENDERPATH_D3D10:
2945 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2947 case RENDERPATH_D3D11:
2948 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2950 case RENDERPATH_GL20:
2951 case RENDERPATH_GLES2:
2952 R_SetupShader_SetPermutationGLSL(mode, permutation);
2953 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2954 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2955 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);
2956 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);
2957 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);
2958 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]);
2959 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]);
2960 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));
2961 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]);
2962 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2964 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2965 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2966 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2967 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2968 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2969 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2971 case RENDERPATH_GL13:
2972 case RENDERPATH_GL11:
2974 case RENDERPATH_SOFT:
2975 R_SetupShader_SetPermutationGLSL(mode, permutation);
2976 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2977 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2978 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2979 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2980 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2981 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2982 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]);
2983 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));
2984 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2985 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2987 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2988 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2989 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2990 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2991 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2992 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2997 #define SKINFRAME_HASH 1024
3001 int loadsequence; // incremented each level change
3002 memexpandablearray_t array;
3003 skinframe_t *hash[SKINFRAME_HASH];
3006 r_skinframe_t r_skinframe;
3008 void R_SkinFrame_PrepareForPurge(void)
3010 r_skinframe.loadsequence++;
3011 // wrap it without hitting zero
3012 if (r_skinframe.loadsequence >= 200)
3013 r_skinframe.loadsequence = 1;
3016 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3020 // mark the skinframe as used for the purging code
3021 skinframe->loadsequence = r_skinframe.loadsequence;
3024 void R_SkinFrame_Purge(void)
3028 for (i = 0;i < SKINFRAME_HASH;i++)
3030 for (s = r_skinframe.hash[i];s;s = s->next)
3032 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3034 if (s->merged == s->base)
3036 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3037 R_PurgeTexture(s->stain );s->stain = NULL;
3038 R_PurgeTexture(s->merged);s->merged = NULL;
3039 R_PurgeTexture(s->base );s->base = NULL;
3040 R_PurgeTexture(s->pants );s->pants = NULL;
3041 R_PurgeTexture(s->shirt );s->shirt = NULL;
3042 R_PurgeTexture(s->nmap );s->nmap = NULL;
3043 R_PurgeTexture(s->gloss );s->gloss = NULL;
3044 R_PurgeTexture(s->glow );s->glow = NULL;
3045 R_PurgeTexture(s->fog );s->fog = NULL;
3046 R_PurgeTexture(s->reflect);s->reflect = NULL;
3047 s->loadsequence = 0;
3053 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3055 char basename[MAX_QPATH];
3057 Image_StripImageExtension(name, basename, sizeof(basename));
3059 if( last == NULL ) {
3061 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3062 item = r_skinframe.hash[hashindex];
3067 // linearly search through the hash bucket
3068 for( ; item ; item = item->next ) {
3069 if( !strcmp( item->basename, basename ) ) {
3076 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3080 char basename[MAX_QPATH];
3082 Image_StripImageExtension(name, basename, sizeof(basename));
3084 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3085 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3086 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3090 rtexture_t *dyntexture;
3091 // check whether its a dynamic texture
3092 dyntexture = CL_GetDynTexture( basename );
3093 if (!add && !dyntexture)
3095 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3096 memset(item, 0, sizeof(*item));
3097 strlcpy(item->basename, basename, sizeof(item->basename));
3098 item->base = dyntexture; // either NULL or dyntexture handle
3099 item->textureflags = textureflags;
3100 item->comparewidth = comparewidth;
3101 item->compareheight = compareheight;
3102 item->comparecrc = comparecrc;
3103 item->next = r_skinframe.hash[hashindex];
3104 r_skinframe.hash[hashindex] = item;
3106 else if( item->base == NULL )
3108 rtexture_t *dyntexture;
3109 // check whether its a dynamic texture
3110 // 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]
3111 dyntexture = CL_GetDynTexture( basename );
3112 item->base = dyntexture; // either NULL or dyntexture handle
3115 R_SkinFrame_MarkUsed(item);
3119 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3121 unsigned long long avgcolor[5], wsum; \
3129 for(pix = 0; pix < cnt; ++pix) \
3132 for(comp = 0; comp < 3; ++comp) \
3134 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3137 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3139 for(comp = 0; comp < 3; ++comp) \
3140 avgcolor[comp] += getpixel * w; \
3143 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3144 avgcolor[4] += getpixel; \
3146 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3148 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3149 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3150 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3151 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3154 extern cvar_t gl_picmip;
3155 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3158 unsigned char *pixels;
3159 unsigned char *bumppixels;
3160 unsigned char *basepixels = NULL;
3161 int basepixels_width = 0;
3162 int basepixels_height = 0;
3163 skinframe_t *skinframe;
3164 rtexture_t *ddsbase = NULL;
3165 qboolean ddshasalpha = false;
3166 float ddsavgcolor[4];
3167 char basename[MAX_QPATH];
3168 int miplevel = R_PicmipForFlags(textureflags);
3169 int savemiplevel = miplevel;
3172 if (cls.state == ca_dedicated)
3175 // return an existing skinframe if already loaded
3176 // if loading of the first image fails, don't make a new skinframe as it
3177 // would cause all future lookups of this to be missing
3178 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3179 if (skinframe && skinframe->base)
3182 Image_StripImageExtension(name, basename, sizeof(basename));
3184 // check for DDS texture file first
3185 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3187 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3188 if (basepixels == NULL)
3192 // FIXME handle miplevel
3194 if (developer_loading.integer)
3195 Con_Printf("loading skin \"%s\"\n", name);
3197 // we've got some pixels to store, so really allocate this new texture now
3199 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3200 skinframe->stain = NULL;
3201 skinframe->merged = NULL;
3202 skinframe->base = NULL;
3203 skinframe->pants = NULL;
3204 skinframe->shirt = NULL;
3205 skinframe->nmap = NULL;
3206 skinframe->gloss = NULL;
3207 skinframe->glow = NULL;
3208 skinframe->fog = NULL;
3209 skinframe->reflect = NULL;
3210 skinframe->hasalpha = false;
3214 skinframe->base = ddsbase;
3215 skinframe->hasalpha = ddshasalpha;
3216 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3217 if (r_loadfog && skinframe->hasalpha)
3218 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3219 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3223 basepixels_width = image_width;
3224 basepixels_height = image_height;
3225 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);
3226 if (textureflags & TEXF_ALPHA)
3228 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3230 if (basepixels[j] < 255)
3232 skinframe->hasalpha = true;
3236 if (r_loadfog && skinframe->hasalpha)
3238 // has transparent pixels
3239 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3240 for (j = 0;j < image_width * image_height * 4;j += 4)
3245 pixels[j+3] = basepixels[j+3];
3247 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);
3251 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3252 //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]);
3253 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3254 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3255 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3256 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3261 mymiplevel = savemiplevel;
3262 if (r_loadnormalmap)
3263 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);
3264 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3266 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3267 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3268 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3269 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3272 // _norm is the name used by tenebrae and has been adopted as standard
3273 if (r_loadnormalmap && skinframe->nmap == NULL)
3275 mymiplevel = savemiplevel;
3276 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3278 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);
3282 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3284 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3285 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3286 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);
3288 Mem_Free(bumppixels);
3290 else if (r_shadow_bumpscale_basetexture.value > 0)
3292 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3293 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3294 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);
3297 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3298 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3301 // _luma is supported only for tenebrae compatibility
3302 // _glow is the preferred name
3303 mymiplevel = savemiplevel;
3304 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))))
3306 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);
3307 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3308 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3309 Mem_Free(pixels);pixels = NULL;
3312 mymiplevel = savemiplevel;
3313 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3315 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);
3316 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3317 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3322 mymiplevel = savemiplevel;
3323 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3325 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);
3326 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3327 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3332 mymiplevel = savemiplevel;
3333 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3335 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);
3336 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3337 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3342 mymiplevel = savemiplevel;
3343 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3345 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);
3346 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3347 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3353 Mem_Free(basepixels);
3358 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3359 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3362 unsigned char *temp1, *temp2;
3363 skinframe_t *skinframe;
3365 if (cls.state == ca_dedicated)
3368 // if already loaded just return it, otherwise make a new skinframe
3369 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3370 if (skinframe && skinframe->base)
3373 skinframe->stain = NULL;
3374 skinframe->merged = NULL;
3375 skinframe->base = NULL;
3376 skinframe->pants = NULL;
3377 skinframe->shirt = NULL;
3378 skinframe->nmap = NULL;
3379 skinframe->gloss = NULL;
3380 skinframe->glow = NULL;
3381 skinframe->fog = NULL;
3382 skinframe->reflect = NULL;
3383 skinframe->hasalpha = false;
3385 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3389 if (developer_loading.integer)
3390 Con_Printf("loading 32bit skin \"%s\"\n", name);
3392 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3394 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3395 temp2 = temp1 + width * height * 4;
3396 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3397 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);
3400 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3401 if (textureflags & TEXF_ALPHA)
3403 for (i = 3;i < width * height * 4;i += 4)
3405 if (skindata[i] < 255)
3407 skinframe->hasalpha = true;
3411 if (r_loadfog && skinframe->hasalpha)
3413 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3414 memcpy(fogpixels, skindata, width * height * 4);
3415 for (i = 0;i < width * height * 4;i += 4)
3416 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3417 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3418 Mem_Free(fogpixels);
3422 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3423 //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]);
3428 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3432 skinframe_t *skinframe;
3434 if (cls.state == ca_dedicated)
3437 // if already loaded just return it, otherwise make a new skinframe
3438 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3439 if (skinframe && skinframe->base)
3442 skinframe->stain = NULL;
3443 skinframe->merged = NULL;
3444 skinframe->base = NULL;
3445 skinframe->pants = NULL;
3446 skinframe->shirt = NULL;
3447 skinframe->nmap = NULL;
3448 skinframe->gloss = NULL;
3449 skinframe->glow = NULL;
3450 skinframe->fog = NULL;
3451 skinframe->reflect = NULL;
3452 skinframe->hasalpha = false;
3454 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3458 if (developer_loading.integer)
3459 Con_Printf("loading quake skin \"%s\"\n", name);
3461 // 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)
3462 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3463 memcpy(skinframe->qpixels, skindata, width*height);
3464 skinframe->qwidth = width;
3465 skinframe->qheight = height;
3468 for (i = 0;i < width * height;i++)
3469 featuresmask |= palette_featureflags[skindata[i]];
3471 skinframe->hasalpha = false;
3472 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3473 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3474 skinframe->qgeneratemerged = true;
3475 skinframe->qgeneratebase = skinframe->qhascolormapping;
3476 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3478 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3479 //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]);
3484 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3488 unsigned char *skindata;
3490 if (!skinframe->qpixels)
3493 if (!skinframe->qhascolormapping)
3494 colormapped = false;
3498 if (!skinframe->qgeneratebase)
3503 if (!skinframe->qgeneratemerged)
3507 width = skinframe->qwidth;
3508 height = skinframe->qheight;
3509 skindata = skinframe->qpixels;
3511 if (skinframe->qgeneratenmap)
3513 unsigned char *temp1, *temp2;
3514 skinframe->qgeneratenmap = false;
3515 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3516 temp2 = temp1 + width * height * 4;
3517 // use either a custom palette or the quake palette
3518 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3519 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3520 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);
3524 if (skinframe->qgenerateglow)
3526 skinframe->qgenerateglow = false;
3527 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3532 skinframe->qgeneratebase = false;
3533 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);
3534 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3535 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3539 skinframe->qgeneratemerged = false;
3540 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);
3543 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3545 Mem_Free(skinframe->qpixels);
3546 skinframe->qpixels = NULL;
3550 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)
3553 skinframe_t *skinframe;
3555 if (cls.state == ca_dedicated)
3558 // if already loaded just return it, otherwise make a new skinframe
3559 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3560 if (skinframe && skinframe->base)
3563 skinframe->stain = NULL;
3564 skinframe->merged = NULL;
3565 skinframe->base = NULL;
3566 skinframe->pants = NULL;
3567 skinframe->shirt = NULL;
3568 skinframe->nmap = NULL;
3569 skinframe->gloss = NULL;
3570 skinframe->glow = NULL;
3571 skinframe->fog = NULL;
3572 skinframe->reflect = NULL;
3573 skinframe->hasalpha = false;
3575 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3579 if (developer_loading.integer)
3580 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3582 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3583 if (textureflags & TEXF_ALPHA)
3585 for (i = 0;i < width * height;i++)
3587 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3589 skinframe->hasalpha = true;
3593 if (r_loadfog && skinframe->hasalpha)
3594 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3597 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3598 //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]);
3603 skinframe_t *R_SkinFrame_LoadMissing(void)
3605 skinframe_t *skinframe;
3607 if (cls.state == ca_dedicated)
3610 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3611 skinframe->stain = NULL;
3612 skinframe->merged = NULL;
3613 skinframe->base = NULL;
3614 skinframe->pants = NULL;
3615 skinframe->shirt = NULL;
3616 skinframe->nmap = NULL;
3617 skinframe->gloss = NULL;
3618 skinframe->glow = NULL;
3619 skinframe->fog = NULL;
3620 skinframe->reflect = NULL;
3621 skinframe->hasalpha = false;
3623 skinframe->avgcolor[0] = rand() / RAND_MAX;
3624 skinframe->avgcolor[1] = rand() / RAND_MAX;
3625 skinframe->avgcolor[2] = rand() / RAND_MAX;
3626 skinframe->avgcolor[3] = 1;
3631 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3632 typedef struct suffixinfo_s
3635 qboolean flipx, flipy, flipdiagonal;
3638 static suffixinfo_t suffix[3][6] =
3641 {"px", false, false, false},
3642 {"nx", false, false, false},
3643 {"py", false, false, false},
3644 {"ny", false, false, false},
3645 {"pz", false, false, false},
3646 {"nz", false, false, false}
3649 {"posx", false, false, false},
3650 {"negx", false, false, false},
3651 {"posy", false, false, false},
3652 {"negy", false, false, false},
3653 {"posz", false, false, false},
3654 {"negz", false, false, false}
3657 {"rt", true, false, true},
3658 {"lf", false, true, true},
3659 {"ft", true, true, false},
3660 {"bk", false, false, false},
3661 {"up", true, false, true},
3662 {"dn", true, false, true}
3666 static int componentorder[4] = {0, 1, 2, 3};
3668 rtexture_t *R_LoadCubemap(const char *basename)
3670 int i, j, cubemapsize;
3671 unsigned char *cubemappixels, *image_buffer;
3672 rtexture_t *cubemaptexture;
3674 // must start 0 so the first loadimagepixels has no requested width/height
3676 cubemappixels = NULL;
3677 cubemaptexture = NULL;
3678 // keep trying different suffix groups (posx, px, rt) until one loads
3679 for (j = 0;j < 3 && !cubemappixels;j++)
3681 // load the 6 images in the suffix group
3682 for (i = 0;i < 6;i++)
3684 // generate an image name based on the base and and suffix
3685 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3687 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3689 // an image loaded, make sure width and height are equal
3690 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3692 // if this is the first image to load successfully, allocate the cubemap memory
3693 if (!cubemappixels && image_width >= 1)
3695 cubemapsize = image_width;
3696 // note this clears to black, so unavailable sides are black
3697 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3699 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3701 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);
3704 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3706 Mem_Free(image_buffer);
3710 // if a cubemap loaded, upload it
3713 if (developer_loading.integer)
3714 Con_Printf("loading cubemap \"%s\"\n", basename);
3716 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3717 Mem_Free(cubemappixels);
3721 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3722 if (developer_loading.integer)
3724 Con_Printf("(tried tried images ");
3725 for (j = 0;j < 3;j++)
3726 for (i = 0;i < 6;i++)
3727 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3728 Con_Print(" and was unable to find any of them).\n");
3731 return cubemaptexture;
3734 rtexture_t *R_GetCubemap(const char *basename)
3737 for (i = 0;i < r_texture_numcubemaps;i++)
3738 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3739 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3740 if (i >= MAX_CUBEMAPS)
3741 return r_texture_whitecube;
3742 r_texture_numcubemaps++;
3743 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3744 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3745 return r_texture_cubemaps[i].texture;
3748 void R_FreeCubemaps(void)
3751 for (i = 0;i < r_texture_numcubemaps;i++)
3753 if (developer_loading.integer)
3754 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3755 if (r_texture_cubemaps[i].texture)
3756 R_FreeTexture(r_texture_cubemaps[i].texture);
3758 r_texture_numcubemaps = 0;
3761 void R_Main_FreeViewCache(void)
3763 if (r_refdef.viewcache.entityvisible)
3764 Mem_Free(r_refdef.viewcache.entityvisible);
3765 if (r_refdef.viewcache.world_pvsbits)
3766 Mem_Free(r_refdef.viewcache.world_pvsbits);
3767 if (r_refdef.viewcache.world_leafvisible)
3768 Mem_Free(r_refdef.viewcache.world_leafvisible);
3769 if (r_refdef.viewcache.world_surfacevisible)
3770 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3771 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3774 void R_Main_ResizeViewCache(void)
3776 int numentities = r_refdef.scene.numentities;
3777 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3778 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3779 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3780 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3781 if (r_refdef.viewcache.maxentities < numentities)
3783 r_refdef.viewcache.maxentities = numentities;
3784 if (r_refdef.viewcache.entityvisible)
3785 Mem_Free(r_refdef.viewcache.entityvisible);
3786 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3788 if (r_refdef.viewcache.world_numclusters != numclusters)
3790 r_refdef.viewcache.world_numclusters = numclusters;
3791 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3792 if (r_refdef.viewcache.world_pvsbits)
3793 Mem_Free(r_refdef.viewcache.world_pvsbits);
3794 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3796 if (r_refdef.viewcache.world_numleafs != numleafs)
3798 r_refdef.viewcache.world_numleafs = numleafs;
3799 if (r_refdef.viewcache.world_leafvisible)
3800 Mem_Free(r_refdef.viewcache.world_leafvisible);
3801 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3803 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3805 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3806 if (r_refdef.viewcache.world_surfacevisible)
3807 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3808 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3812 extern rtexture_t *loadingscreentexture;
3813 void gl_main_start(void)
3815 loadingscreentexture = NULL;
3816 r_texture_blanknormalmap = NULL;
3817 r_texture_white = NULL;
3818 r_texture_grey128 = NULL;
3819 r_texture_black = NULL;
3820 r_texture_whitecube = NULL;
3821 r_texture_normalizationcube = NULL;
3822 r_texture_fogattenuation = NULL;
3823 r_texture_fogheighttexture = NULL;
3824 r_texture_gammaramps = NULL;
3825 r_texture_numcubemaps = 0;
3827 r_loaddds = r_texture_dds_load.integer != 0;
3828 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3830 switch(vid.renderpath)
3832 case RENDERPATH_GL20:
3833 case RENDERPATH_D3D9:
3834 case RENDERPATH_D3D10:
3835 case RENDERPATH_D3D11:
3836 case RENDERPATH_SOFT:
3837 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3838 Cvar_SetValueQuick(&gl_combine, 1);
3839 Cvar_SetValueQuick(&r_glsl, 1);
3840 r_loadnormalmap = true;
3844 case RENDERPATH_GL13:
3845 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3846 Cvar_SetValueQuick(&gl_combine, 1);
3847 Cvar_SetValueQuick(&r_glsl, 0);
3848 r_loadnormalmap = false;
3849 r_loadgloss = false;
3852 case RENDERPATH_GL11:
3853 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3854 Cvar_SetValueQuick(&gl_combine, 0);
3855 Cvar_SetValueQuick(&r_glsl, 0);
3856 r_loadnormalmap = false;
3857 r_loadgloss = false;
3860 case RENDERPATH_GLES2:
3861 Cvar_SetValueQuick(&r_textureunits, 1);
3862 Cvar_SetValueQuick(&gl_combine, 1);
3863 Cvar_SetValueQuick(&r_glsl, 1);
3864 r_loadnormalmap = true;
3865 r_loadgloss = false;
3871 R_FrameData_Reset();
3875 memset(r_queries, 0, sizeof(r_queries));
3877 r_qwskincache = NULL;
3878 r_qwskincache_size = 0;
3880 // set up r_skinframe loading system for textures
3881 memset(&r_skinframe, 0, sizeof(r_skinframe));
3882 r_skinframe.loadsequence = 1;
3883 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3885 r_main_texturepool = R_AllocTexturePool();
3886 R_BuildBlankTextures();
3888 if (vid.support.arb_texture_cube_map)
3891 R_BuildNormalizationCube();
3893 r_texture_fogattenuation = NULL;
3894 r_texture_fogheighttexture = NULL;
3895 r_texture_gammaramps = NULL;
3896 //r_texture_fogintensity = NULL;
3897 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3898 memset(&r_waterstate, 0, sizeof(r_waterstate));
3899 r_glsl_permutation = NULL;
3900 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3901 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3902 glslshaderstring = NULL;
3904 r_hlsl_permutation = NULL;
3905 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3906 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3908 hlslshaderstring = NULL;
3909 memset(&r_svbsp, 0, sizeof (r_svbsp));
3911 r_refdef.fogmasktable_density = 0;
3914 void gl_main_shutdown(void)
3917 R_FrameData_Reset();
3919 R_Main_FreeViewCache();
3921 switch(vid.renderpath)
3923 case RENDERPATH_GL11:
3924 case RENDERPATH_GL13:
3925 case RENDERPATH_GL20:
3926 case RENDERPATH_GLES2:
3928 qglDeleteQueriesARB(r_maxqueries, r_queries);
3930 case RENDERPATH_D3D9:
3931 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3933 case RENDERPATH_D3D10:
3934 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3936 case RENDERPATH_D3D11:
3937 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3939 case RENDERPATH_SOFT:
3945 memset(r_queries, 0, sizeof(r_queries));
3947 r_qwskincache = NULL;
3948 r_qwskincache_size = 0;
3950 // clear out the r_skinframe state
3951 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3952 memset(&r_skinframe, 0, sizeof(r_skinframe));
3955 Mem_Free(r_svbsp.nodes);
3956 memset(&r_svbsp, 0, sizeof (r_svbsp));
3957 R_FreeTexturePool(&r_main_texturepool);
3958 loadingscreentexture = NULL;
3959 r_texture_blanknormalmap = NULL;
3960 r_texture_white = NULL;
3961 r_texture_grey128 = NULL;
3962 r_texture_black = NULL;
3963 r_texture_whitecube = NULL;
3964 r_texture_normalizationcube = NULL;
3965 r_texture_fogattenuation = NULL;
3966 r_texture_fogheighttexture = NULL;
3967 r_texture_gammaramps = NULL;
3968 r_texture_numcubemaps = 0;
3969 //r_texture_fogintensity = NULL;
3970 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3971 memset(&r_waterstate, 0, sizeof(r_waterstate));
3974 r_glsl_permutation = NULL;
3975 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3976 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3977 glslshaderstring = NULL;
3979 r_hlsl_permutation = NULL;
3980 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3981 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3983 hlslshaderstring = NULL;
3986 extern void CL_ParseEntityLump(char *entitystring);
3987 void gl_main_newmap(void)
3989 // FIXME: move this code to client
3990 char *entities, entname[MAX_QPATH];
3992 Mem_Free(r_qwskincache);
3993 r_qwskincache = NULL;
3994 r_qwskincache_size = 0;
3997 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3998 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4000 CL_ParseEntityLump(entities);
4004 if (cl.worldmodel->brush.entities)
4005 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4007 R_Main_FreeViewCache();
4009 R_FrameData_Reset();
4012 void GL_Main_Init(void)
4014 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4016 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4017 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4018 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4019 if (gamemode == GAME_NEHAHRA)
4021 Cvar_RegisterVariable (&gl_fogenable);
4022 Cvar_RegisterVariable (&gl_fogdensity);
4023 Cvar_RegisterVariable (&gl_fogred);
4024 Cvar_RegisterVariable (&gl_foggreen);
4025 Cvar_RegisterVariable (&gl_fogblue);
4026 Cvar_RegisterVariable (&gl_fogstart);
4027 Cvar_RegisterVariable (&gl_fogend);
4028 Cvar_RegisterVariable (&gl_skyclip);
4030 Cvar_RegisterVariable(&r_motionblur);
4031 Cvar_RegisterVariable(&r_motionblur_maxblur);
4032 Cvar_RegisterVariable(&r_motionblur_bmin);
4033 Cvar_RegisterVariable(&r_motionblur_vmin);
4034 Cvar_RegisterVariable(&r_motionblur_vmax);
4035 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4036 Cvar_RegisterVariable(&r_motionblur_randomize);
4037 Cvar_RegisterVariable(&r_damageblur);
4038 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4039 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4040 Cvar_RegisterVariable(&r_equalize_entities_by);
4041 Cvar_RegisterVariable(&r_equalize_entities_to);
4042 Cvar_RegisterVariable(&r_depthfirst);
4043 Cvar_RegisterVariable(&r_useinfinitefarclip);
4044 Cvar_RegisterVariable(&r_farclip_base);
4045 Cvar_RegisterVariable(&r_farclip_world);
4046 Cvar_RegisterVariable(&r_nearclip);
4047 Cvar_RegisterVariable(&r_showbboxes);
4048 Cvar_RegisterVariable(&r_showsurfaces);
4049 Cvar_RegisterVariable(&r_showtris);
4050 Cvar_RegisterVariable(&r_shownormals);
4051 Cvar_RegisterVariable(&r_showlighting);
4052 Cvar_RegisterVariable(&r_showshadowvolumes);
4053 Cvar_RegisterVariable(&r_showcollisionbrushes);
4054 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4055 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4056 Cvar_RegisterVariable(&r_showdisabledepthtest);
4057 Cvar_RegisterVariable(&r_drawportals);
4058 Cvar_RegisterVariable(&r_drawentities);
4059 Cvar_RegisterVariable(&r_draw2d);
4060 Cvar_RegisterVariable(&r_drawworld);
4061 Cvar_RegisterVariable(&r_cullentities_trace);
4062 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4063 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4064 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4065 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4066 Cvar_RegisterVariable(&r_drawviewmodel);
4067 Cvar_RegisterVariable(&r_drawexteriormodel);
4068 Cvar_RegisterVariable(&r_speeds);
4069 Cvar_RegisterVariable(&r_fullbrights);
4070 Cvar_RegisterVariable(&r_wateralpha);
4071 Cvar_RegisterVariable(&r_dynamic);
4072 Cvar_RegisterVariable(&r_fakelight);
4073 Cvar_RegisterVariable(&r_fakelight_intensity);
4074 Cvar_RegisterVariable(&r_fullbright);
4075 Cvar_RegisterVariable(&r_shadows);
4076 Cvar_RegisterVariable(&r_shadows_darken);
4077 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4078 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4079 Cvar_RegisterVariable(&r_shadows_throwdistance);
4080 Cvar_RegisterVariable(&r_shadows_throwdirection);
4081 Cvar_RegisterVariable(&r_shadows_focus);
4082 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4083 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4084 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4085 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4086 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4087 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4088 Cvar_RegisterVariable(&r_fog_exp2);
4089 Cvar_RegisterVariable(&r_drawfog);
4090 Cvar_RegisterVariable(&r_transparentdepthmasking);
4091 Cvar_RegisterVariable(&r_texture_dds_load);
4092 Cvar_RegisterVariable(&r_texture_dds_save);
4093 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4094 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4095 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4096 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4097 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4098 Cvar_RegisterVariable(&r_textureunits);
4099 Cvar_RegisterVariable(&gl_combine);
4100 Cvar_RegisterVariable(&r_glsl);
4101 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4102 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4103 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4104 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4105 Cvar_RegisterVariable(&r_glsl_postprocess);
4106 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4107 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4108 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4109 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4110 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4111 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4112 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4113 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4115 Cvar_RegisterVariable(&r_water);
4116 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4117 Cvar_RegisterVariable(&r_water_clippingplanebias);
4118 Cvar_RegisterVariable(&r_water_refractdistort);
4119 Cvar_RegisterVariable(&r_water_reflectdistort);
4120 Cvar_RegisterVariable(&r_water_scissormode);
4121 Cvar_RegisterVariable(&r_lerpsprites);
4122 Cvar_RegisterVariable(&r_lerpmodels);
4123 Cvar_RegisterVariable(&r_lerplightstyles);
4124 Cvar_RegisterVariable(&r_waterscroll);
4125 Cvar_RegisterVariable(&r_bloom);
4126 Cvar_RegisterVariable(&r_bloom_colorscale);
4127 Cvar_RegisterVariable(&r_bloom_brighten);
4128 Cvar_RegisterVariable(&r_bloom_blur);
4129 Cvar_RegisterVariable(&r_bloom_resolution);
4130 Cvar_RegisterVariable(&r_bloom_colorexponent);
4131 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4132 Cvar_RegisterVariable(&r_hdr);
4133 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4134 Cvar_RegisterVariable(&r_hdr_glowintensity);
4135 Cvar_RegisterVariable(&r_hdr_range);
4136 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4137 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4138 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4139 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4140 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4141 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4142 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4143 Cvar_RegisterVariable(&developer_texturelogging);
4144 Cvar_RegisterVariable(&gl_lightmaps);
4145 Cvar_RegisterVariable(&r_test);
4146 Cvar_RegisterVariable(&r_glsl_saturation);
4147 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4148 Cvar_RegisterVariable(&r_framedatasize);
4149 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4150 Cvar_SetValue("r_fullbrights", 0);
4151 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4153 Cvar_RegisterVariable(&r_track_sprites);
4154 Cvar_RegisterVariable(&r_track_sprites_flags);
4155 Cvar_RegisterVariable(&r_track_sprites_scalew);
4156 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4157 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4158 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4159 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4160 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4163 extern void R_Textures_Init(void);
4164 extern void GL_Draw_Init(void);
4165 extern void GL_Main_Init(void);
4166 extern void R_Shadow_Init(void);
4167 extern void R_Sky_Init(void);
4168 extern void GL_Surf_Init(void);
4169 extern void R_Particles_Init(void);
4170 extern void R_Explosion_Init(void);
4171 extern void gl_backend_init(void);
4172 extern void Sbar_Init(void);
4173 extern void R_LightningBeams_Init(void);
4174 extern void Mod_RenderInit(void);
4175 extern void Font_Init(void);
4177 void Render_Init(void)
4190 R_LightningBeams_Init();
4199 extern char *ENGINE_EXTENSIONS;
4202 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4203 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4204 gl_version = (const char *)qglGetString(GL_VERSION);
4205 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4209 if (!gl_platformextensions)
4210 gl_platformextensions = "";
4212 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4213 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4214 Con_Printf("GL_VERSION: %s\n", gl_version);
4215 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4216 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4218 VID_CheckExtensions();
4220 // LordHavoc: report supported extensions
4221 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4223 // clear to black (loading plaque will be seen over this)
4224 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4227 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4231 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4233 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4236 p = r_refdef.view.frustum + i;
4241 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4245 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4249 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4253 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4257 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4261 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4265 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4269 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4277 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4281 for (i = 0;i < numplanes;i++)
4288 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4292 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4296 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4300 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4304 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4308 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4312 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4316 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4324 //==================================================================================
4326 // LordHavoc: this stores temporary data used within the same frame
4328 typedef struct r_framedata_mem_s
4330 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4331 size_t size; // how much usable space
4332 size_t current; // how much space in use
4333 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4334 size_t wantedsize; // how much space was allocated
4335 unsigned char *data; // start of real data (16byte aligned)
4339 static r_framedata_mem_t *r_framedata_mem;
4341 void R_FrameData_Reset(void)
4343 while (r_framedata_mem)
4345 r_framedata_mem_t *next = r_framedata_mem->purge;
4346 Mem_Free(r_framedata_mem);
4347 r_framedata_mem = next;
4351 void R_FrameData_Resize(void)
4354 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4355 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4356 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4358 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4359 newmem->wantedsize = wantedsize;
4360 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4361 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4362 newmem->current = 0;
4364 newmem->purge = r_framedata_mem;
4365 r_framedata_mem = newmem;
4369 void R_FrameData_NewFrame(void)
4371 R_FrameData_Resize();
4372 if (!r_framedata_mem)
4374 // if we ran out of space on the last frame, free the old memory now
4375 while (r_framedata_mem->purge)
4377 // repeatedly remove the second item in the list, leaving only head
4378 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4379 Mem_Free(r_framedata_mem->purge);
4380 r_framedata_mem->purge = next;
4382 // reset the current mem pointer
4383 r_framedata_mem->current = 0;
4384 r_framedata_mem->mark = 0;
4387 void *R_FrameData_Alloc(size_t size)
4391 // align to 16 byte boundary - the data pointer is already aligned, so we
4392 // only need to ensure the size of every allocation is also aligned
4393 size = (size + 15) & ~15;
4395 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4397 // emergency - we ran out of space, allocate more memory
4398 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4399 R_FrameData_Resize();
4402 data = r_framedata_mem->data + r_framedata_mem->current;
4403 r_framedata_mem->current += size;
4405 // count the usage for stats
4406 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4407 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4409 return (void *)data;
4412 void *R_FrameData_Store(size_t size, void *data)
4414 void *d = R_FrameData_Alloc(size);
4416 memcpy(d, data, size);
4420 void R_FrameData_SetMark(void)
4422 if (!r_framedata_mem)
4424 r_framedata_mem->mark = r_framedata_mem->current;
4427 void R_FrameData_ReturnToMark(void)
4429 if (!r_framedata_mem)
4431 r_framedata_mem->current = r_framedata_mem->mark;
4434 //==================================================================================
4436 // LordHavoc: animcache originally written by Echon, rewritten since then
4439 * Animation cache prevents re-generating mesh data for an animated model
4440 * multiple times in one frame for lighting, shadowing, reflections, etc.
4443 void R_AnimCache_Free(void)
4447 void R_AnimCache_ClearCache(void)
4450 entity_render_t *ent;
4452 for (i = 0;i < r_refdef.scene.numentities;i++)
4454 ent = r_refdef.scene.entities[i];
4455 ent->animcache_vertex3f = NULL;
4456 ent->animcache_normal3f = NULL;
4457 ent->animcache_svector3f = NULL;
4458 ent->animcache_tvector3f = NULL;
4459 ent->animcache_vertexmesh = NULL;
4460 ent->animcache_vertex3fbuffer = NULL;
4461 ent->animcache_vertexmeshbuffer = NULL;
4465 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4469 // check if we need the meshbuffers
4470 if (!vid.useinterleavedarrays)
4473 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4474 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4475 // TODO: upload vertex3f buffer?
4476 if (ent->animcache_vertexmesh)
4478 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4479 for (i = 0;i < numvertices;i++)
4480 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4481 if (ent->animcache_svector3f)
4482 for (i = 0;i < numvertices;i++)
4483 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4484 if (ent->animcache_tvector3f)
4485 for (i = 0;i < numvertices;i++)
4486 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4487 if (ent->animcache_normal3f)
4488 for (i = 0;i < numvertices;i++)
4489 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4490 // TODO: upload vertexmeshbuffer?
4494 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4496 dp_model_t *model = ent->model;
4498 // see if it's already cached this frame
4499 if (ent->animcache_vertex3f)
4501 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4502 if (wantnormals || wanttangents)
4504 if (ent->animcache_normal3f)
4505 wantnormals = false;
4506 if (ent->animcache_svector3f)
4507 wanttangents = false;
4508 if (wantnormals || wanttangents)
4510 numvertices = model->surfmesh.num_vertices;
4512 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4515 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4516 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4518 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4519 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4525 // see if this ent is worth caching
4526 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4528 // get some memory for this entity and generate mesh data
4529 numvertices = model->surfmesh.num_vertices;
4530 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4532 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4535 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4536 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4538 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4539 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4544 void R_AnimCache_CacheVisibleEntities(void)
4547 qboolean wantnormals = true;
4548 qboolean wanttangents = !r_showsurfaces.integer;
4550 switch(vid.renderpath)
4552 case RENDERPATH_GL20:
4553 case RENDERPATH_D3D9:
4554 case RENDERPATH_D3D10:
4555 case RENDERPATH_D3D11:
4556 case RENDERPATH_GLES2:
4558 case RENDERPATH_GL13:
4559 case RENDERPATH_GL11:
4560 wanttangents = false;
4562 case RENDERPATH_SOFT:
4566 if (r_shownormals.integer)
4567 wanttangents = wantnormals = true;
4569 // TODO: thread this
4570 // NOTE: R_PrepareRTLights() also caches entities
4572 for (i = 0;i < r_refdef.scene.numentities;i++)
4573 if (r_refdef.viewcache.entityvisible[i])
4574 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4577 //==================================================================================
4579 static void R_View_UpdateEntityLighting (void)
4582 entity_render_t *ent;
4583 vec3_t tempdiffusenormal, avg;
4584 vec_t f, fa, fd, fdd;
4585 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4587 for (i = 0;i < r_refdef.scene.numentities;i++)
4589 ent = r_refdef.scene.entities[i];
4591 // skip unseen models
4592 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4596 if (ent->model && ent->model->brush.num_leafs)
4598 // TODO: use modellight for r_ambient settings on world?
4599 VectorSet(ent->modellight_ambient, 0, 0, 0);
4600 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4601 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4605 // fetch the lighting from the worldmodel data
4606 VectorClear(ent->modellight_ambient);
4607 VectorClear(ent->modellight_diffuse);
4608 VectorClear(tempdiffusenormal);
4609 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4612 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4614 // complete lightning for lit sprites
4615 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4616 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4618 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4619 org[2] = org[2] + r_overheadsprites_pushback.value;
4620 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4623 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4625 if(ent->flags & RENDER_EQUALIZE)
4627 // first fix up ambient lighting...
4628 if(r_equalize_entities_minambient.value > 0)
4630 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4633 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4634 if(fa < r_equalize_entities_minambient.value * fd)
4637 // fa'/fd' = minambient
4638 // fa'+0.25*fd' = fa+0.25*fd
4640 // fa' = fd' * minambient
4641 // fd'*(0.25+minambient) = fa+0.25*fd
4643 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4644 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4646 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4647 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
4648 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4649 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4654 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4656 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4657 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4661 // adjust brightness and saturation to target
4662 avg[0] = avg[1] = avg[2] = fa / f;
4663 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4664 avg[0] = avg[1] = avg[2] = fd / f;
4665 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4671 VectorSet(ent->modellight_ambient, 1, 1, 1);
4673 // move the light direction into modelspace coordinates for lighting code
4674 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4675 if(VectorLength2(ent->modellight_lightdir) == 0)
4676 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4677 VectorNormalize(ent->modellight_lightdir);
4681 #define MAX_LINEOFSIGHTTRACES 64
4683 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4686 vec3_t boxmins, boxmaxs;
4689 dp_model_t *model = r_refdef.scene.worldmodel;
4691 if (!model || !model->brush.TraceLineOfSight)
4694 // expand the box a little
4695 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4696 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4697 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4698 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4699 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4700 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4702 // return true if eye is inside enlarged box
4703 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4707 VectorCopy(eye, start);
4708 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4709 if (model->brush.TraceLineOfSight(model, start, end))
4712 // try various random positions
4713 for (i = 0;i < numsamples;i++)
4715 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4716 if (model->brush.TraceLineOfSight(model, start, end))
4724 static void R_View_UpdateEntityVisible (void)
4729 entity_render_t *ent;
4731 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4732 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4733 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4734 : RENDER_EXTERIORMODEL;
4735 if (!r_drawviewmodel.integer)
4736 renderimask |= RENDER_VIEWMODEL;
4737 if (!r_drawexteriormodel.integer)
4738 renderimask |= RENDER_EXTERIORMODEL;
4739 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4741 // worldmodel can check visibility
4742 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4743 for (i = 0;i < r_refdef.scene.numentities;i++)
4745 ent = r_refdef.scene.entities[i];
4746 if (!(ent->flags & renderimask))
4747 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)))
4748 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))
4749 r_refdef.viewcache.entityvisible[i] = true;
4751 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4752 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4754 for (i = 0;i < r_refdef.scene.numentities;i++)
4756 ent = r_refdef.scene.entities[i];
4757 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4759 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4761 continue; // temp entities do pvs only
4762 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4763 ent->last_trace_visibility = realtime;
4764 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4765 r_refdef.viewcache.entityvisible[i] = 0;
4772 // no worldmodel or it can't check visibility
4773 for (i = 0;i < r_refdef.scene.numentities;i++)
4775 ent = r_refdef.scene.entities[i];
4776 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));
4781 /// only used if skyrendermasked, and normally returns false
4782 int R_DrawBrushModelsSky (void)
4785 entity_render_t *ent;
4788 for (i = 0;i < r_refdef.scene.numentities;i++)
4790 if (!r_refdef.viewcache.entityvisible[i])
4792 ent = r_refdef.scene.entities[i];
4793 if (!ent->model || !ent->model->DrawSky)
4795 ent->model->DrawSky(ent);
4801 static void R_DrawNoModel(entity_render_t *ent);
4802 static void R_DrawModels(void)
4805 entity_render_t *ent;
4807 for (i = 0;i < r_refdef.scene.numentities;i++)
4809 if (!r_refdef.viewcache.entityvisible[i])
4811 ent = r_refdef.scene.entities[i];
4812 r_refdef.stats.entities++;
4813 if (ent->model && ent->model->Draw != NULL)
4814 ent->model->Draw(ent);
4820 static void R_DrawModelsDepth(void)
4823 entity_render_t *ent;
4825 for (i = 0;i < r_refdef.scene.numentities;i++)
4827 if (!r_refdef.viewcache.entityvisible[i])
4829 ent = r_refdef.scene.entities[i];
4830 if (ent->model && ent->model->DrawDepth != NULL)
4831 ent->model->DrawDepth(ent);
4835 static void R_DrawModelsDebug(void)
4838 entity_render_t *ent;
4840 for (i = 0;i < r_refdef.scene.numentities;i++)
4842 if (!r_refdef.viewcache.entityvisible[i])
4844 ent = r_refdef.scene.entities[i];
4845 if (ent->model && ent->model->DrawDebug != NULL)
4846 ent->model->DrawDebug(ent);
4850 static void R_DrawModelsAddWaterPlanes(void)
4853 entity_render_t *ent;
4855 for (i = 0;i < r_refdef.scene.numentities;i++)
4857 if (!r_refdef.viewcache.entityvisible[i])
4859 ent = r_refdef.scene.entities[i];
4860 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4861 ent->model->DrawAddWaterPlanes(ent);
4865 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4867 if (r_hdr_irisadaptation.integer)
4871 vec3_t diffusenormal;
4876 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4877 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4878 brightness = max(0.0000001f, brightness);
4879 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4880 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4881 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4882 current = r_hdr_irisadaptation_value.value;
4884 current = min(current + adjust, goal);
4885 else if (current > goal)
4886 current = max(current - adjust, goal);
4887 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4888 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4890 else if (r_hdr_irisadaptation_value.value != 1.0f)
4891 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4894 static void R_View_SetFrustum(const int *scissor)
4897 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4898 vec3_t forward, left, up, origin, v;
4902 // flipped x coordinates (because x points left here)
4903 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4904 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4906 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4907 switch(vid.renderpath)
4909 case RENDERPATH_D3D9:
4910 case RENDERPATH_D3D10:
4911 case RENDERPATH_D3D11:
4912 case RENDERPATH_SOFT:
4913 // non-flipped y coordinates
4914 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4915 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4917 case RENDERPATH_GL11:
4918 case RENDERPATH_GL13:
4919 case RENDERPATH_GL20:
4920 case RENDERPATH_GLES2:
4921 // non-flipped y coordinates
4922 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4923 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4928 // we can't trust r_refdef.view.forward and friends in reflected scenes
4929 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4932 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4933 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4934 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4935 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4936 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4937 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4938 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4939 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4940 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4941 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4942 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4943 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4947 zNear = r_refdef.nearclip;
4948 nudge = 1.0 - 1.0 / (1<<23);
4949 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4950 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4951 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4952 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4953 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4954 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4955 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4956 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4962 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4963 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4964 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4965 r_refdef.view.frustum[0].dist = m[15] - m[12];
4967 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4968 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4969 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4970 r_refdef.view.frustum[1].dist = m[15] + m[12];
4972 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4973 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4974 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4975 r_refdef.view.frustum[2].dist = m[15] - m[13];
4977 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4978 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4979 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4980 r_refdef.view.frustum[3].dist = m[15] + m[13];
4982 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4983 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4984 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4985 r_refdef.view.frustum[4].dist = m[15] - m[14];
4987 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4988 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4989 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4990 r_refdef.view.frustum[5].dist = m[15] + m[14];
4993 if (r_refdef.view.useperspective)
4995 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4996 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]);
4997 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]);
4998 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]);
4999 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]);
5001 // then the normals from the corners relative to origin
5002 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5003 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5004 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5005 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5007 // in a NORMAL view, forward cross left == up
5008 // in a REFLECTED view, forward cross left == down
5009 // so our cross products above need to be adjusted for a left handed coordinate system
5010 CrossProduct(forward, left, v);
5011 if(DotProduct(v, up) < 0)
5013 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5014 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5015 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5016 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5019 // Leaving those out was a mistake, those were in the old code, and they
5020 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5021 // I couldn't reproduce it after adding those normalizations. --blub
5022 VectorNormalize(r_refdef.view.frustum[0].normal);
5023 VectorNormalize(r_refdef.view.frustum[1].normal);
5024 VectorNormalize(r_refdef.view.frustum[2].normal);
5025 VectorNormalize(r_refdef.view.frustum[3].normal);
5027 // make the corners absolute
5028 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5029 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5030 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5031 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5034 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5036 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5037 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5038 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5039 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5040 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5044 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5045 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5046 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5047 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5048 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5049 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5050 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5051 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5052 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5053 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5055 r_refdef.view.numfrustumplanes = 5;
5057 if (r_refdef.view.useclipplane)
5059 r_refdef.view.numfrustumplanes = 6;
5060 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5063 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5064 PlaneClassify(r_refdef.view.frustum + i);
5066 // LordHavoc: note to all quake engine coders, Quake had a special case
5067 // for 90 degrees which assumed a square view (wrong), so I removed it,
5068 // Quake2 has it disabled as well.
5070 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5071 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5072 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5073 //PlaneClassify(&frustum[0]);
5075 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5076 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5077 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5078 //PlaneClassify(&frustum[1]);
5080 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5081 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5082 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5083 //PlaneClassify(&frustum[2]);
5085 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5086 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5087 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5088 //PlaneClassify(&frustum[3]);
5091 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5092 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5093 //PlaneClassify(&frustum[4]);
5096 void R_View_UpdateWithScissor(const int *myscissor)
5098 R_Main_ResizeViewCache();
5099 R_View_SetFrustum(myscissor);
5100 R_View_WorldVisibility(r_refdef.view.useclipplane);
5101 R_View_UpdateEntityVisible();
5102 R_View_UpdateEntityLighting();
5105 void R_View_Update(void)
5107 R_Main_ResizeViewCache();
5108 R_View_SetFrustum(NULL);
5109 R_View_WorldVisibility(r_refdef.view.useclipplane);
5110 R_View_UpdateEntityVisible();
5111 R_View_UpdateEntityLighting();
5114 void R_SetupView(qboolean allowwaterclippingplane)
5116 const float *customclipplane = NULL;
5118 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5120 // LordHavoc: couldn't figure out how to make this approach the
5121 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5122 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5123 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5124 dist = r_refdef.view.clipplane.dist;
5125 plane[0] = r_refdef.view.clipplane.normal[0];
5126 plane[1] = r_refdef.view.clipplane.normal[1];
5127 plane[2] = r_refdef.view.clipplane.normal[2];
5129 customclipplane = plane;
5132 if (!r_refdef.view.useperspective)
5133 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);
5134 else if (vid.stencil && r_useinfinitefarclip.integer)
5135 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);
5137 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);
5138 R_SetViewport(&r_refdef.view.viewport);
5141 void R_EntityMatrix(const matrix4x4_t *matrix)
5143 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5145 gl_modelmatrixchanged = false;
5146 gl_modelmatrix = *matrix;
5147 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5148 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5149 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5150 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5152 switch(vid.renderpath)
5154 case RENDERPATH_D3D9:
5156 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5157 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5160 case RENDERPATH_D3D10:
5161 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5163 case RENDERPATH_D3D11:
5164 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5166 case RENDERPATH_GL13:
5167 case RENDERPATH_GL11:
5168 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5170 case RENDERPATH_SOFT:
5171 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5172 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5174 case RENDERPATH_GL20:
5175 case RENDERPATH_GLES2:
5176 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5177 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5183 void R_ResetViewRendering2D(void)
5185 r_viewport_t viewport;
5188 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5189 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);
5190 R_SetViewport(&viewport);
5191 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5192 GL_Color(1, 1, 1, 1);
5193 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5194 GL_BlendFunc(GL_ONE, GL_ZERO);
5195 GL_ScissorTest(false);
5196 GL_DepthMask(false);
5197 GL_DepthRange(0, 1);
5198 GL_DepthTest(false);
5199 GL_DepthFunc(GL_LEQUAL);
5200 R_EntityMatrix(&identitymatrix);
5201 R_Mesh_ResetTextureState();
5202 GL_PolygonOffset(0, 0);
5203 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5204 switch(vid.renderpath)
5206 case RENDERPATH_GL11:
5207 case RENDERPATH_GL13:
5208 case RENDERPATH_GL20:
5209 case RENDERPATH_GLES2:
5210 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5212 case RENDERPATH_D3D9:
5213 case RENDERPATH_D3D10:
5214 case RENDERPATH_D3D11:
5215 case RENDERPATH_SOFT:
5218 GL_CullFace(GL_NONE);
5221 void R_ResetViewRendering3D(void)
5226 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5227 GL_Color(1, 1, 1, 1);
5228 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5229 GL_BlendFunc(GL_ONE, GL_ZERO);
5230 GL_ScissorTest(true);
5232 GL_DepthRange(0, 1);
5234 GL_DepthFunc(GL_LEQUAL);
5235 R_EntityMatrix(&identitymatrix);
5236 R_Mesh_ResetTextureState();
5237 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5238 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5239 switch(vid.renderpath)
5241 case RENDERPATH_GL11:
5242 case RENDERPATH_GL13:
5243 case RENDERPATH_GL20:
5244 case RENDERPATH_GLES2:
5245 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5247 case RENDERPATH_D3D9:
5248 case RENDERPATH_D3D10:
5249 case RENDERPATH_D3D11:
5250 case RENDERPATH_SOFT:
5253 GL_CullFace(r_refdef.view.cullface_back);
5258 R_RenderView_UpdateViewVectors
5261 static void R_RenderView_UpdateViewVectors(void)
5263 // break apart the view matrix into vectors for various purposes
5264 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5265 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5266 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5267 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5268 // make an inverted copy of the view matrix for tracking sprites
5269 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5272 void R_RenderScene(void);
5273 void R_RenderWaterPlanes(void);
5275 static void R_Water_StartFrame(void)
5278 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5279 r_waterstate_waterplane_t *p;
5281 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5284 switch(vid.renderpath)
5286 case RENDERPATH_GL20:
5287 case RENDERPATH_D3D9:
5288 case RENDERPATH_D3D10:
5289 case RENDERPATH_D3D11:
5290 case RENDERPATH_SOFT:
5291 case RENDERPATH_GLES2:
5293 case RENDERPATH_GL13:
5294 case RENDERPATH_GL11:
5298 // set waterwidth and waterheight to the water resolution that will be
5299 // used (often less than the screen resolution for faster rendering)
5300 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5301 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5303 // calculate desired texture sizes
5304 // can't use water if the card does not support the texture size
5305 if (!r_water.integer || r_showsurfaces.integer)
5306 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5307 else if (vid.support.arb_texture_non_power_of_two)
5309 texturewidth = waterwidth;
5310 textureheight = waterheight;
5311 camerawidth = waterwidth;
5312 cameraheight = waterheight;
5316 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5317 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5318 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5319 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5322 // allocate textures as needed
5323 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5325 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5326 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5328 if (p->texture_refraction)
5329 R_FreeTexture(p->texture_refraction);
5330 p->texture_refraction = NULL;
5331 if (p->texture_reflection)
5332 R_FreeTexture(p->texture_reflection);
5333 p->texture_reflection = NULL;
5334 if (p->texture_camera)
5335 R_FreeTexture(p->texture_camera);
5336 p->texture_camera = NULL;
5338 memset(&r_waterstate, 0, sizeof(r_waterstate));
5339 r_waterstate.texturewidth = texturewidth;
5340 r_waterstate.textureheight = textureheight;
5341 r_waterstate.camerawidth = camerawidth;
5342 r_waterstate.cameraheight = cameraheight;
5345 if (r_waterstate.texturewidth)
5347 r_waterstate.enabled = true;
5349 // when doing a reduced render (HDR) we want to use a smaller area
5350 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5351 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5353 // set up variables that will be used in shader setup
5354 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5355 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5356 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5357 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5360 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5361 r_waterstate.numwaterplanes = 0;
5364 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5366 int triangleindex, planeindex;
5372 r_waterstate_waterplane_t *p;
5373 texture_t *t = R_GetCurrentTexture(surface->texture);
5375 // just use the first triangle with a valid normal for any decisions
5376 VectorClear(normal);
5377 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5379 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5380 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5381 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5382 TriangleNormal(vert[0], vert[1], vert[2], normal);
5383 if (VectorLength2(normal) >= 0.001)
5387 VectorCopy(normal, plane.normal);
5388 VectorNormalize(plane.normal);
5389 plane.dist = DotProduct(vert[0], plane.normal);
5390 PlaneClassify(&plane);
5391 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5393 // skip backfaces (except if nocullface is set)
5394 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5396 VectorNegate(plane.normal, plane.normal);
5398 PlaneClassify(&plane);
5402 // find a matching plane if there is one
5403 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5404 if(p->camera_entity == t->camera_entity)
5405 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5407 if (planeindex >= r_waterstate.maxwaterplanes)
5408 return; // nothing we can do, out of planes
5410 // if this triangle does not fit any known plane rendered this frame, add one
5411 if (planeindex >= r_waterstate.numwaterplanes)
5413 // store the new plane
5414 r_waterstate.numwaterplanes++;
5416 // clear materialflags and pvs
5417 p->materialflags = 0;
5418 p->pvsvalid = false;
5419 p->camera_entity = t->camera_entity;
5420 VectorCopy(surface->mins, p->mins);
5421 VectorCopy(surface->maxs, p->maxs);
5426 p->mins[0] = min(p->mins[0], surface->mins[0]);
5427 p->mins[1] = min(p->mins[1], surface->mins[1]);
5428 p->mins[2] = min(p->mins[2], surface->mins[2]);
5429 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5430 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5431 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5433 // merge this surface's materialflags into the waterplane
5434 p->materialflags |= t->currentmaterialflags;
5435 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5437 // merge this surface's PVS into the waterplane
5438 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5439 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5440 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5442 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5448 static void R_Water_ProcessPlanes(void)
5451 r_refdef_view_t originalview;
5452 r_refdef_view_t myview;
5454 r_waterstate_waterplane_t *p;
5457 originalview = r_refdef.view;
5459 // make sure enough textures are allocated
5460 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5462 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5464 if (!p->texture_refraction)
5465 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);
5466 if (!p->texture_refraction)
5469 else if (p->materialflags & MATERIALFLAG_CAMERA)
5471 if (!p->texture_camera)
5472 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);
5473 if (!p->texture_camera)
5477 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5479 if (!p->texture_reflection)
5480 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);
5481 if (!p->texture_reflection)
5487 r_refdef.view = originalview;
5488 r_refdef.view.showdebug = false;
5489 r_refdef.view.width = r_waterstate.waterwidth;
5490 r_refdef.view.height = r_waterstate.waterheight;
5491 r_refdef.view.useclipplane = true;
5492 myview = r_refdef.view;
5493 r_waterstate.renderingscene = true;
5494 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5496 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
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 // render reflected scene and copy into texture
5507 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5508 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5509 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5510 r_refdef.view.clipplane = p->plane;
5512 // reverse the cullface settings for this render
5513 r_refdef.view.cullface_front = GL_FRONT;
5514 r_refdef.view.cullface_back = GL_BACK;
5515 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5517 r_refdef.view.usecustompvs = true;
5519 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5521 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5524 R_ResetViewRendering3D();
5525 R_ClearScreen(r_refdef.fogenabled);
5526 if(r_water_scissormode.integer & 2)
5527 R_View_UpdateWithScissor(myscissor);
5530 if(r_water_scissormode.integer & 1)
5531 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5534 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);
5537 // render the normal view scene and copy into texture
5538 // (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)
5539 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5541 r_refdef.view = myview;
5542 if(r_water_scissormode.integer)
5545 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5546 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5549 r_waterstate.renderingrefraction = true;
5551 r_refdef.view.clipplane = p->plane;
5552 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5553 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5555 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5557 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5558 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5559 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5560 R_RenderView_UpdateViewVectors();
5561 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5563 r_refdef.view.usecustompvs = true;
5564 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);
5568 PlaneClassify(&r_refdef.view.clipplane);
5570 R_ResetViewRendering3D();
5571 R_ClearScreen(r_refdef.fogenabled);
5572 if(r_water_scissormode.integer & 2)
5573 R_View_UpdateWithScissor(myscissor);
5576 if(r_water_scissormode.integer & 1)
5577 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5580 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);
5581 r_waterstate.renderingrefraction = false;
5583 else if (p->materialflags & MATERIALFLAG_CAMERA)
5585 r_refdef.view = myview;
5587 r_refdef.view.clipplane = p->plane;
5588 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5589 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5591 r_refdef.view.width = r_waterstate.camerawidth;
5592 r_refdef.view.height = r_waterstate.cameraheight;
5593 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5594 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5596 if(p->camera_entity)
5598 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5599 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5602 // note: all of the view is used for displaying... so
5603 // there is no use in scissoring
5605 // reverse the cullface settings for this render
5606 r_refdef.view.cullface_front = GL_FRONT;
5607 r_refdef.view.cullface_back = GL_BACK;
5608 // also reverse the view matrix
5609 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
5610 R_RenderView_UpdateViewVectors();
5611 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5613 r_refdef.view.usecustompvs = true;
5614 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);
5617 // camera needs no clipplane
5618 r_refdef.view.useclipplane = false;
5620 PlaneClassify(&r_refdef.view.clipplane);
5622 R_ResetViewRendering3D();
5623 R_ClearScreen(r_refdef.fogenabled);
5627 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);
5628 r_waterstate.renderingrefraction = false;
5632 r_waterstate.renderingscene = false;
5633 r_refdef.view = originalview;
5634 R_ResetViewRendering3D();
5635 R_ClearScreen(r_refdef.fogenabled);
5639 r_refdef.view = originalview;
5640 r_waterstate.renderingscene = false;
5641 Cvar_SetValueQuick(&r_water, 0);
5642 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5646 void R_Bloom_StartFrame(void)
5648 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5650 switch(vid.renderpath)
5652 case RENDERPATH_GL20:
5653 case RENDERPATH_D3D9:
5654 case RENDERPATH_D3D10:
5655 case RENDERPATH_D3D11:
5656 case RENDERPATH_SOFT:
5657 case RENDERPATH_GLES2:
5659 case RENDERPATH_GL13:
5660 case RENDERPATH_GL11:
5664 // set bloomwidth and bloomheight to the bloom resolution that will be
5665 // used (often less than the screen resolution for faster rendering)
5666 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5667 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5668 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5669 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5670 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5672 // calculate desired texture sizes
5673 if (vid.support.arb_texture_non_power_of_two)
5675 screentexturewidth = r_refdef.view.width;
5676 screentextureheight = r_refdef.view.height;
5677 bloomtexturewidth = r_bloomstate.bloomwidth;
5678 bloomtextureheight = r_bloomstate.bloomheight;
5682 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5683 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5684 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5685 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5688 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))
5690 Cvar_SetValueQuick(&r_hdr, 0);
5691 Cvar_SetValueQuick(&r_bloom, 0);
5692 Cvar_SetValueQuick(&r_motionblur, 0);
5693 Cvar_SetValueQuick(&r_damageblur, 0);
5696 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)))
5697 screentexturewidth = screentextureheight = 0;
5698 if (!r_hdr.integer && !r_bloom.integer)
5699 bloomtexturewidth = bloomtextureheight = 0;
5701 // allocate textures as needed
5702 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5704 if (r_bloomstate.texture_screen)
5705 R_FreeTexture(r_bloomstate.texture_screen);
5706 r_bloomstate.texture_screen = NULL;
5707 r_bloomstate.screentexturewidth = screentexturewidth;
5708 r_bloomstate.screentextureheight = screentextureheight;
5709 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5710 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);
5712 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5714 if (r_bloomstate.texture_bloom)
5715 R_FreeTexture(r_bloomstate.texture_bloom);
5716 r_bloomstate.texture_bloom = NULL;
5717 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5718 r_bloomstate.bloomtextureheight = bloomtextureheight;
5719 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5720 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);
5723 // when doing a reduced render (HDR) we want to use a smaller area
5724 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5725 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5726 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5727 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5728 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5730 // set up a texcoord array for the full resolution screen image
5731 // (we have to keep this around to copy back during final render)
5732 r_bloomstate.screentexcoord2f[0] = 0;
5733 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5734 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5735 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5736 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5737 r_bloomstate.screentexcoord2f[5] = 0;
5738 r_bloomstate.screentexcoord2f[6] = 0;
5739 r_bloomstate.screentexcoord2f[7] = 0;
5741 // set up a texcoord array for the reduced resolution bloom image
5742 // (which will be additive blended over the screen image)
5743 r_bloomstate.bloomtexcoord2f[0] = 0;
5744 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5745 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5746 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5747 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5748 r_bloomstate.bloomtexcoord2f[5] = 0;
5749 r_bloomstate.bloomtexcoord2f[6] = 0;
5750 r_bloomstate.bloomtexcoord2f[7] = 0;
5752 switch(vid.renderpath)
5754 case RENDERPATH_GL11:
5755 case RENDERPATH_GL13:
5756 case RENDERPATH_GL20:
5757 case RENDERPATH_SOFT:
5758 case RENDERPATH_GLES2:
5760 case RENDERPATH_D3D9:
5761 case RENDERPATH_D3D10:
5762 case RENDERPATH_D3D11:
5765 for (i = 0;i < 4;i++)
5767 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5768 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5769 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5770 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5776 if (r_hdr.integer || r_bloom.integer)
5778 r_bloomstate.enabled = true;
5779 r_bloomstate.hdr = r_hdr.integer != 0;
5782 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);
5785 void R_Bloom_CopyBloomTexture(float colorscale)
5787 r_refdef.stats.bloom++;
5789 // scale down screen texture to the bloom texture size
5791 R_SetViewport(&r_bloomstate.viewport);
5792 GL_BlendFunc(GL_ONE, GL_ZERO);
5793 GL_Color(colorscale, colorscale, colorscale, 1);
5794 // 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...
5795 switch(vid.renderpath)
5797 case RENDERPATH_GL11:
5798 case RENDERPATH_GL13:
5799 case RENDERPATH_GL20:
5800 case RENDERPATH_SOFT:
5801 case RENDERPATH_GLES2:
5802 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5804 case RENDERPATH_D3D9:
5805 case RENDERPATH_D3D10:
5806 case RENDERPATH_D3D11:
5807 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5810 // TODO: do boxfilter scale-down in shader?
5811 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5812 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5813 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5815 // we now have a bloom image in the framebuffer
5816 // copy it into the bloom image texture for later processing
5817 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5818 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5821 void R_Bloom_CopyHDRTexture(void)
5823 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);
5824 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5827 void R_Bloom_MakeTexture(void)
5830 float xoffset, yoffset, r, brighten;
5832 r_refdef.stats.bloom++;
5834 R_ResetViewRendering2D();
5836 // we have a bloom image in the framebuffer
5838 R_SetViewport(&r_bloomstate.viewport);
5840 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5843 r = bound(0, r_bloom_colorexponent.value / x, 1);
5844 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5846 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5847 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5848 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5849 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5851 // copy the vertically blurred bloom view to a texture
5852 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);
5853 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5856 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5857 brighten = r_bloom_brighten.value;
5859 brighten *= r_hdr_range.value;
5860 brighten = sqrt(brighten);
5862 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5863 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5865 for (dir = 0;dir < 2;dir++)
5867 // blend on at multiple vertical offsets to achieve a vertical blur
5868 // TODO: do offset blends using GLSL
5869 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5870 GL_BlendFunc(GL_ONE, GL_ZERO);
5871 for (x = -range;x <= range;x++)
5873 if (!dir){xoffset = 0;yoffset = x;}
5874 else {xoffset = x;yoffset = 0;}
5875 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5876 yoffset /= (float)r_bloomstate.bloomtextureheight;
5877 // compute a texcoord array with the specified x and y offset
5878 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5879 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5880 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5881 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5882 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5883 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5884 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5885 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5886 // this r value looks like a 'dot' particle, fading sharply to
5887 // black at the edges
5888 // (probably not realistic but looks good enough)
5889 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5890 //r = brighten/(range*2+1);
5891 r = brighten / (range * 2 + 1);
5893 r *= (1 - x*x/(float)(range*range));
5894 GL_Color(r, r, r, 1);
5895 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5896 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5897 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5898 GL_BlendFunc(GL_ONE, GL_ONE);
5901 // copy the vertically blurred bloom view to a texture
5902 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);
5903 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5907 void R_HDR_RenderBloomTexture(void)
5909 int oldwidth, oldheight;
5910 float oldcolorscale;
5911 qboolean oldwaterstate;
5913 oldwaterstate = r_waterstate.enabled;
5914 oldcolorscale = r_refdef.view.colorscale;
5915 oldwidth = r_refdef.view.width;
5916 oldheight = r_refdef.view.height;
5917 r_refdef.view.width = r_bloomstate.bloomwidth;
5918 r_refdef.view.height = r_bloomstate.bloomheight;
5920 if(r_hdr.integer < 2)
5921 r_waterstate.enabled = false;
5923 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5924 // TODO: add exposure compensation features
5925 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5927 r_refdef.view.showdebug = false;
5928 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5930 R_ResetViewRendering3D();
5932 R_ClearScreen(r_refdef.fogenabled);
5933 if (r_timereport_active)
5934 R_TimeReport("HDRclear");
5937 if (r_timereport_active)
5938 R_TimeReport("visibility");
5940 // only do secondary renders with HDR if r_hdr is 2 or higher
5941 r_waterstate.numwaterplanes = 0;
5942 if (r_waterstate.enabled)
5943 R_RenderWaterPlanes();
5945 r_refdef.view.showdebug = true;
5947 r_waterstate.numwaterplanes = 0;
5949 R_ResetViewRendering2D();
5951 R_Bloom_CopyHDRTexture();
5952 R_Bloom_MakeTexture();
5954 // restore the view settings
5955 r_waterstate.enabled = oldwaterstate;
5956 r_refdef.view.width = oldwidth;
5957 r_refdef.view.height = oldheight;
5958 r_refdef.view.colorscale = oldcolorscale;
5960 R_ResetViewRendering3D();
5962 R_ClearScreen(r_refdef.fogenabled);
5963 if (r_timereport_active)
5964 R_TimeReport("viewclear");
5967 static void R_BlendView(void)
5969 unsigned int permutation;
5970 float uservecs[4][4];
5972 switch (vid.renderpath)
5974 case RENDERPATH_GL20:
5975 case RENDERPATH_D3D9:
5976 case RENDERPATH_D3D10:
5977 case RENDERPATH_D3D11:
5978 case RENDERPATH_SOFT:
5979 case RENDERPATH_GLES2:
5981 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5982 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5983 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5984 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5985 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5987 if (r_bloomstate.texture_screen)
5989 // make sure the buffer is available
5990 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5992 R_ResetViewRendering2D();
5994 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5996 // declare variables
5998 static float avgspeed;
6000 speed = VectorLength(cl.movement_velocity);
6002 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6003 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6005 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6006 speed = bound(0, speed, 1);
6007 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6009 // calculate values into a standard alpha
6010 cl.motionbluralpha = 1 - exp(-
6012 (r_motionblur.value * speed / 80)
6014 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6017 max(0.0001, cl.time - cl.oldtime) // fps independent
6020 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6021 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6023 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6025 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6026 GL_Color(1, 1, 1, cl.motionbluralpha);
6027 switch(vid.renderpath)
6029 case RENDERPATH_GL11:
6030 case RENDERPATH_GL13:
6031 case RENDERPATH_GL20:
6032 case RENDERPATH_SOFT:
6033 case RENDERPATH_GLES2:
6034 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6036 case RENDERPATH_D3D9:
6037 case RENDERPATH_D3D10:
6038 case RENDERPATH_D3D11:
6039 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6042 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6043 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6044 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6048 // copy view into the screen texture
6049 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);
6050 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6052 else if (!r_bloomstate.texture_bloom)
6054 // we may still have to do view tint...
6055 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6057 // apply a color tint to the whole view
6058 R_ResetViewRendering2D();
6059 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6060 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6061 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6062 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6063 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6065 break; // no screen processing, no bloom, skip it
6068 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6070 // render simple bloom effect
6071 // copy the screen and shrink it and darken it for the bloom process
6072 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6073 // make the bloom texture
6074 R_Bloom_MakeTexture();
6077 #if _MSC_VER >= 1400
6078 #define sscanf sscanf_s
6080 memset(uservecs, 0, sizeof(uservecs));
6081 if (r_glsl_postprocess_uservec1_enable.integer)
6082 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6083 if (r_glsl_postprocess_uservec2_enable.integer)
6084 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6085 if (r_glsl_postprocess_uservec3_enable.integer)
6086 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6087 if (r_glsl_postprocess_uservec4_enable.integer)
6088 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6090 R_ResetViewRendering2D();
6091 GL_Color(1, 1, 1, 1);
6092 GL_BlendFunc(GL_ONE, GL_ZERO);
6094 switch(vid.renderpath)
6096 case RENDERPATH_GL20:
6097 case RENDERPATH_GLES2:
6098 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6099 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6100 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6101 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6102 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6103 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]);
6104 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6105 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]);
6106 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]);
6107 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]);
6108 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]);
6109 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6110 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6111 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);
6113 case RENDERPATH_D3D9:
6115 // 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...
6116 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6117 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6118 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6119 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6120 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6121 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6122 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6123 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6124 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6125 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6126 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6127 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6128 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6129 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6132 case RENDERPATH_D3D10:
6133 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6135 case RENDERPATH_D3D11:
6136 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6138 case RENDERPATH_SOFT:
6139 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6140 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6141 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6142 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6143 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6144 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6145 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6146 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6147 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6148 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6149 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6150 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6151 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6152 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6157 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6158 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6160 case RENDERPATH_GL13:
6161 case RENDERPATH_GL11:
6162 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6164 // apply a color tint to the whole view
6165 R_ResetViewRendering2D();
6166 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6167 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6168 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6169 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6170 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6176 matrix4x4_t r_waterscrollmatrix;
6178 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6180 if (r_refdef.fog_density)
6182 r_refdef.fogcolor[0] = r_refdef.fog_red;
6183 r_refdef.fogcolor[1] = r_refdef.fog_green;
6184 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6186 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6187 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6188 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6189 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6193 VectorCopy(r_refdef.fogcolor, fogvec);
6194 // color.rgb *= ContrastBoost * SceneBrightness;
6195 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6196 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6197 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6198 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6203 void R_UpdateVariables(void)
6207 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6209 r_refdef.farclip = r_farclip_base.value;
6210 if (r_refdef.scene.worldmodel)
6211 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6212 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6214 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6215 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6216 r_refdef.polygonfactor = 0;
6217 r_refdef.polygonoffset = 0;
6218 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6219 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6221 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6222 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6223 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6224 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6225 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6226 if (FAKELIGHT_ENABLED)
6228 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6230 if (r_showsurfaces.integer)
6232 r_refdef.scene.rtworld = false;
6233 r_refdef.scene.rtworldshadows = false;
6234 r_refdef.scene.rtdlight = false;
6235 r_refdef.scene.rtdlightshadows = false;
6236 r_refdef.lightmapintensity = 0;
6239 if (gamemode == GAME_NEHAHRA)
6241 if (gl_fogenable.integer)
6243 r_refdef.oldgl_fogenable = true;
6244 r_refdef.fog_density = gl_fogdensity.value;
6245 r_refdef.fog_red = gl_fogred.value;
6246 r_refdef.fog_green = gl_foggreen.value;
6247 r_refdef.fog_blue = gl_fogblue.value;
6248 r_refdef.fog_alpha = 1;
6249 r_refdef.fog_start = 0;
6250 r_refdef.fog_end = gl_skyclip.value;
6251 r_refdef.fog_height = 1<<30;
6252 r_refdef.fog_fadedepth = 128;
6254 else if (r_refdef.oldgl_fogenable)
6256 r_refdef.oldgl_fogenable = false;
6257 r_refdef.fog_density = 0;
6258 r_refdef.fog_red = 0;
6259 r_refdef.fog_green = 0;
6260 r_refdef.fog_blue = 0;
6261 r_refdef.fog_alpha = 0;
6262 r_refdef.fog_start = 0;
6263 r_refdef.fog_end = 0;
6264 r_refdef.fog_height = 1<<30;
6265 r_refdef.fog_fadedepth = 128;
6269 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6270 r_refdef.fog_start = max(0, r_refdef.fog_start);
6271 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6273 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6275 if (r_refdef.fog_density && r_drawfog.integer)
6277 r_refdef.fogenabled = true;
6278 // this is the point where the fog reaches 0.9986 alpha, which we
6279 // consider a good enough cutoff point for the texture
6280 // (0.9986 * 256 == 255.6)
6281 if (r_fog_exp2.integer)
6282 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6284 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6285 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6286 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6287 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6288 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6289 R_BuildFogHeightTexture();
6290 // fog color was already set
6291 // update the fog texture
6292 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)
6293 R_BuildFogTexture();
6294 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6295 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6298 r_refdef.fogenabled = false;
6300 switch(vid.renderpath)
6302 case RENDERPATH_GL20:
6303 case RENDERPATH_D3D9:
6304 case RENDERPATH_D3D10:
6305 case RENDERPATH_D3D11:
6306 case RENDERPATH_SOFT:
6307 case RENDERPATH_GLES2:
6308 if(v_glslgamma.integer && !vid_gammatables_trivial)
6310 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6312 // build GLSL gamma texture
6313 #define RAMPWIDTH 256
6314 unsigned short ramp[RAMPWIDTH * 3];
6315 unsigned char rampbgr[RAMPWIDTH][4];
6318 r_texture_gammaramps_serial = vid_gammatables_serial;
6320 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6321 for(i = 0; i < RAMPWIDTH; ++i)
6323 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6324 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6325 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6328 if (r_texture_gammaramps)
6330 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6334 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6340 // remove GLSL gamma texture
6343 case RENDERPATH_GL13:
6344 case RENDERPATH_GL11:
6349 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6350 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6356 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6357 if( scenetype != r_currentscenetype ) {
6358 // store the old scenetype
6359 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6360 r_currentscenetype = scenetype;
6361 // move in the new scene
6362 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6371 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6373 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6374 if( scenetype == r_currentscenetype ) {
6375 return &r_refdef.scene;
6377 return &r_scenes_store[ scenetype ];
6386 int dpsoftrast_test;
6387 void R_RenderView(void)
6389 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6391 dpsoftrast_test = r_test.integer;
6393 if (r_timereport_active)
6394 R_TimeReport("start");
6395 r_textureframe++; // used only by R_GetCurrentTexture
6396 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6398 if(R_CompileShader_CheckStaticParms())
6401 if (!r_drawentities.integer)
6402 r_refdef.scene.numentities = 0;
6404 R_AnimCache_ClearCache();
6405 R_FrameData_NewFrame();
6407 /* adjust for stereo display */
6408 if(R_Stereo_Active())
6410 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);
6411 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6414 if (r_refdef.view.isoverlay)
6416 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6417 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6418 R_TimeReport("depthclear");
6420 r_refdef.view.showdebug = false;
6422 r_waterstate.enabled = false;
6423 r_waterstate.numwaterplanes = 0;
6427 r_refdef.view.matrix = originalmatrix;
6433 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6435 r_refdef.view.matrix = originalmatrix;
6436 return; //Host_Error ("R_RenderView: NULL worldmodel");
6439 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6441 R_RenderView_UpdateViewVectors();
6443 R_Shadow_UpdateWorldLightSelection();
6445 R_Bloom_StartFrame();
6446 R_Water_StartFrame();
6449 if (r_timereport_active)
6450 R_TimeReport("viewsetup");
6452 R_ResetViewRendering3D();
6454 if (r_refdef.view.clear || r_refdef.fogenabled)
6456 R_ClearScreen(r_refdef.fogenabled);
6457 if (r_timereport_active)
6458 R_TimeReport("viewclear");
6460 r_refdef.view.clear = true;
6462 // this produces a bloom texture to be used in R_BlendView() later
6463 if (r_hdr.integer && r_bloomstate.bloomwidth)
6465 R_HDR_RenderBloomTexture();
6466 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6467 r_textureframe++; // used only by R_GetCurrentTexture
6470 r_refdef.view.showdebug = true;
6473 if (r_timereport_active)
6474 R_TimeReport("visibility");
6476 r_waterstate.numwaterplanes = 0;
6477 if (r_waterstate.enabled)
6478 R_RenderWaterPlanes();
6481 r_waterstate.numwaterplanes = 0;
6484 if (r_timereport_active)
6485 R_TimeReport("blendview");
6487 GL_Scissor(0, 0, vid.width, vid.height);
6488 GL_ScissorTest(false);
6490 r_refdef.view.matrix = originalmatrix;
6495 void R_RenderWaterPlanes(void)
6497 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6499 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6500 if (r_timereport_active)
6501 R_TimeReport("waterworld");
6504 // don't let sound skip if going slow
6505 if (r_refdef.scene.extraupdate)
6508 R_DrawModelsAddWaterPlanes();
6509 if (r_timereport_active)
6510 R_TimeReport("watermodels");
6512 if (r_waterstate.numwaterplanes)
6514 R_Water_ProcessPlanes();
6515 if (r_timereport_active)
6516 R_TimeReport("waterscenes");
6520 extern void R_DrawLightningBeams (void);
6521 extern void VM_CL_AddPolygonsToMeshQueue (void);
6522 extern void R_DrawPortals (void);
6523 extern cvar_t cl_locs_show;
6524 static void R_DrawLocs(void);
6525 static void R_DrawEntityBBoxes(void);
6526 static void R_DrawModelDecals(void);
6527 extern void R_DrawModelShadows(void);
6528 extern void R_DrawModelShadowMaps(void);
6529 extern cvar_t cl_decals_newsystem;
6530 extern qboolean r_shadow_usingdeferredprepass;
6531 void R_RenderScene(void)
6533 qboolean shadowmapping = false;
6535 if (r_timereport_active)
6536 R_TimeReport("beginscene");
6538 r_refdef.stats.renders++;
6542 // don't let sound skip if going slow
6543 if (r_refdef.scene.extraupdate)
6546 R_MeshQueue_BeginScene();
6550 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);
6552 if (r_timereport_active)
6553 R_TimeReport("skystartframe");
6555 if (cl.csqc_vidvars.drawworld)
6557 // don't let sound skip if going slow
6558 if (r_refdef.scene.extraupdate)
6561 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6563 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6564 if (r_timereport_active)
6565 R_TimeReport("worldsky");
6568 if (R_DrawBrushModelsSky() && r_timereport_active)
6569 R_TimeReport("bmodelsky");
6571 if (skyrendermasked && skyrenderlater)
6573 // we have to force off the water clipping plane while rendering sky
6577 if (r_timereport_active)
6578 R_TimeReport("sky");
6582 R_AnimCache_CacheVisibleEntities();
6583 if (r_timereport_active)
6584 R_TimeReport("animation");
6586 R_Shadow_PrepareLights();
6587 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6588 R_Shadow_PrepareModelShadows();
6589 if (r_timereport_active)
6590 R_TimeReport("preparelights");
6592 if (R_Shadow_ShadowMappingEnabled())
6593 shadowmapping = true;
6595 if (r_shadow_usingdeferredprepass)
6596 R_Shadow_DrawPrepass();
6598 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6600 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6601 if (r_timereport_active)
6602 R_TimeReport("worlddepth");
6604 if (r_depthfirst.integer >= 2)
6606 R_DrawModelsDepth();
6607 if (r_timereport_active)
6608 R_TimeReport("modeldepth");
6611 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6613 R_DrawModelShadowMaps();
6614 R_ResetViewRendering3D();
6615 // don't let sound skip if going slow
6616 if (r_refdef.scene.extraupdate)
6620 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6622 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6623 if (r_timereport_active)
6624 R_TimeReport("world");
6627 // don't let sound skip if going slow
6628 if (r_refdef.scene.extraupdate)
6632 if (r_timereport_active)
6633 R_TimeReport("models");
6635 // don't let sound skip if going slow
6636 if (r_refdef.scene.extraupdate)
6639 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6641 R_DrawModelShadows();
6642 R_ResetViewRendering3D();
6643 // don't let sound skip if going slow
6644 if (r_refdef.scene.extraupdate)
6648 if (!r_shadow_usingdeferredprepass)
6650 R_Shadow_DrawLights();
6651 if (r_timereport_active)
6652 R_TimeReport("rtlights");
6655 // don't let sound skip if going slow
6656 if (r_refdef.scene.extraupdate)
6659 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6661 R_DrawModelShadows();
6662 R_ResetViewRendering3D();
6663 // don't let sound skip if going slow
6664 if (r_refdef.scene.extraupdate)
6668 if (cl.csqc_vidvars.drawworld)
6670 if (cl_decals_newsystem.integer)
6672 R_DrawModelDecals();
6673 if (r_timereport_active)
6674 R_TimeReport("modeldecals");
6679 if (r_timereport_active)
6680 R_TimeReport("decals");
6684 if (r_timereport_active)
6685 R_TimeReport("particles");
6688 if (r_timereport_active)
6689 R_TimeReport("explosions");
6691 R_DrawLightningBeams();
6692 if (r_timereport_active)
6693 R_TimeReport("lightning");
6696 VM_CL_AddPolygonsToMeshQueue();
6698 if (r_refdef.view.showdebug)
6700 if (cl_locs_show.integer)
6703 if (r_timereport_active)
6704 R_TimeReport("showlocs");
6707 if (r_drawportals.integer)
6710 if (r_timereport_active)
6711 R_TimeReport("portals");
6714 if (r_showbboxes.value > 0)
6716 R_DrawEntityBBoxes();
6717 if (r_timereport_active)
6718 R_TimeReport("bboxes");
6722 R_MeshQueue_RenderTransparent();
6723 if (r_timereport_active)
6724 R_TimeReport("drawtrans");
6726 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))
6728 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6729 if (r_timereport_active)
6730 R_TimeReport("worlddebug");
6731 R_DrawModelsDebug();
6732 if (r_timereport_active)
6733 R_TimeReport("modeldebug");
6736 if (cl.csqc_vidvars.drawworld)
6738 R_Shadow_DrawCoronas();
6739 if (r_timereport_active)
6740 R_TimeReport("coronas");
6745 GL_DepthTest(false);
6746 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6747 GL_Color(1, 1, 1, 1);
6748 qglBegin(GL_POLYGON);
6749 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6750 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6751 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6752 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6754 qglBegin(GL_POLYGON);
6755 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]);
6756 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]);
6757 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]);
6758 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]);
6760 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6764 // don't let sound skip if going slow
6765 if (r_refdef.scene.extraupdate)
6768 R_ResetViewRendering2D();
6771 static const unsigned short bboxelements[36] =
6781 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6784 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6786 RSurf_ActiveWorldEntity();
6788 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6789 GL_DepthMask(false);
6790 GL_DepthRange(0, 1);
6791 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6792 // R_Mesh_ResetTextureState();
6794 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6795 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6796 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6797 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6798 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6799 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6800 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6801 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6802 R_FillColors(color4f, 8, cr, cg, cb, ca);
6803 if (r_refdef.fogenabled)
6805 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6807 f1 = RSurf_FogVertex(v);
6809 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6810 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6811 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6814 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6815 R_Mesh_ResetTextureState();
6816 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6817 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6820 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6824 prvm_edict_t *edict;
6825 prvm_prog_t *prog_save = prog;
6827 // this function draws bounding boxes of server entities
6831 GL_CullFace(GL_NONE);
6832 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6836 for (i = 0;i < numsurfaces;i++)
6838 edict = PRVM_EDICT_NUM(surfacelist[i]);
6839 switch ((int)edict->fields.server->solid)
6841 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6842 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6843 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6844 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6845 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6846 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6848 color[3] *= r_showbboxes.value;
6849 color[3] = bound(0, color[3], 1);
6850 GL_DepthTest(!r_showdisabledepthtest.integer);
6851 GL_CullFace(r_refdef.view.cullface_front);
6852 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6858 static void R_DrawEntityBBoxes(void)
6861 prvm_edict_t *edict;
6863 prvm_prog_t *prog_save = prog;
6865 // this function draws bounding boxes of server entities
6871 for (i = 0;i < prog->num_edicts;i++)
6873 edict = PRVM_EDICT_NUM(i);
6874 if (edict->priv.server->free)
6876 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6877 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6879 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6881 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6882 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6888 static const int nomodelelement3i[24] =
6900 static const unsigned short nomodelelement3s[24] =
6912 static const float nomodelvertex3f[6*3] =
6922 static const float nomodelcolor4f[6*4] =
6924 0.0f, 0.0f, 0.5f, 1.0f,
6925 0.0f, 0.0f, 0.5f, 1.0f,
6926 0.0f, 0.5f, 0.0f, 1.0f,
6927 0.0f, 0.5f, 0.0f, 1.0f,
6928 0.5f, 0.0f, 0.0f, 1.0f,
6929 0.5f, 0.0f, 0.0f, 1.0f
6932 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6938 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);
6940 // this is only called once per entity so numsurfaces is always 1, and
6941 // surfacelist is always {0}, so this code does not handle batches
6943 if (rsurface.ent_flags & RENDER_ADDITIVE)
6945 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6946 GL_DepthMask(false);
6948 else if (rsurface.colormod[3] < 1)
6950 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6951 GL_DepthMask(false);
6955 GL_BlendFunc(GL_ONE, GL_ZERO);
6958 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6959 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6960 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6961 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6962 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6963 for (i = 0, c = color4f;i < 6;i++, c += 4)
6965 c[0] *= rsurface.colormod[0];
6966 c[1] *= rsurface.colormod[1];
6967 c[2] *= rsurface.colormod[2];
6968 c[3] *= rsurface.colormod[3];
6970 if (r_refdef.fogenabled)
6972 for (i = 0, c = color4f;i < 6;i++, c += 4)
6974 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6976 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6977 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6978 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6981 // R_Mesh_ResetTextureState();
6982 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6983 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6984 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6987 void R_DrawNoModel(entity_render_t *ent)
6990 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6991 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6992 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6994 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6997 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6999 vec3_t right1, right2, diff, normal;
7001 VectorSubtract (org2, org1, normal);
7003 // calculate 'right' vector for start
7004 VectorSubtract (r_refdef.view.origin, org1, diff);
7005 CrossProduct (normal, diff, right1);
7006 VectorNormalize (right1);
7008 // calculate 'right' vector for end
7009 VectorSubtract (r_refdef.view.origin, org2, diff);
7010 CrossProduct (normal, diff, right2);
7011 VectorNormalize (right2);
7013 vert[ 0] = org1[0] + width * right1[0];
7014 vert[ 1] = org1[1] + width * right1[1];
7015 vert[ 2] = org1[2] + width * right1[2];
7016 vert[ 3] = org1[0] - width * right1[0];
7017 vert[ 4] = org1[1] - width * right1[1];
7018 vert[ 5] = org1[2] - width * right1[2];
7019 vert[ 6] = org2[0] - width * right2[0];
7020 vert[ 7] = org2[1] - width * right2[1];
7021 vert[ 8] = org2[2] - width * right2[2];
7022 vert[ 9] = org2[0] + width * right2[0];
7023 vert[10] = org2[1] + width * right2[1];
7024 vert[11] = org2[2] + width * right2[2];
7027 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)
7029 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7030 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7031 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7032 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7033 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7034 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7035 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7036 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7037 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7038 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7039 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7040 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7043 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7048 VectorSet(v, x, y, z);
7049 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7050 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7052 if (i == mesh->numvertices)
7054 if (mesh->numvertices < mesh->maxvertices)
7056 VectorCopy(v, vertex3f);
7057 mesh->numvertices++;
7059 return mesh->numvertices;
7065 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7069 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7070 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7071 e = mesh->element3i + mesh->numtriangles * 3;
7072 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7074 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7075 if (mesh->numtriangles < mesh->maxtriangles)
7080 mesh->numtriangles++;
7082 element[1] = element[2];
7086 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7090 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7091 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7092 e = mesh->element3i + mesh->numtriangles * 3;
7093 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7095 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7096 if (mesh->numtriangles < mesh->maxtriangles)
7101 mesh->numtriangles++;
7103 element[1] = element[2];
7107 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7108 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7110 int planenum, planenum2;
7113 mplane_t *plane, *plane2;
7115 double temppoints[2][256*3];
7116 // figure out how large a bounding box we need to properly compute this brush
7118 for (w = 0;w < numplanes;w++)
7119 maxdist = max(maxdist, fabs(planes[w].dist));
7120 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7121 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7122 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7126 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7127 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7129 if (planenum2 == planenum)
7131 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);
7134 if (tempnumpoints < 3)
7136 // generate elements forming a triangle fan for this polygon
7137 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7141 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)
7143 texturelayer_t *layer;
7144 layer = t->currentlayers + t->currentnumlayers++;
7146 layer->depthmask = depthmask;
7147 layer->blendfunc1 = blendfunc1;
7148 layer->blendfunc2 = blendfunc2;
7149 layer->texture = texture;
7150 layer->texmatrix = *matrix;
7151 layer->color[0] = r;
7152 layer->color[1] = g;
7153 layer->color[2] = b;
7154 layer->color[3] = a;
7157 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7159 if(parms[0] == 0 && parms[1] == 0)
7161 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7162 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7167 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7170 index = parms[2] + r_refdef.scene.time * parms[3];
7171 index -= floor(index);
7172 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7175 case Q3WAVEFUNC_NONE:
7176 case Q3WAVEFUNC_NOISE:
7177 case Q3WAVEFUNC_COUNT:
7180 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7181 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7182 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7183 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7184 case Q3WAVEFUNC_TRIANGLE:
7186 f = index - floor(index);
7197 f = parms[0] + parms[1] * f;
7198 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7199 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7203 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7208 matrix4x4_t matrix, temp;
7209 switch(tcmod->tcmod)
7213 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7214 matrix = r_waterscrollmatrix;
7216 matrix = identitymatrix;
7218 case Q3TCMOD_ENTITYTRANSLATE:
7219 // this is used in Q3 to allow the gamecode to control texcoord
7220 // scrolling on the entity, which is not supported in darkplaces yet.
7221 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7223 case Q3TCMOD_ROTATE:
7224 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7225 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7226 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7229 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7231 case Q3TCMOD_SCROLL:
7232 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7234 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7235 w = (int) tcmod->parms[0];
7236 h = (int) tcmod->parms[1];
7237 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7239 idx = (int) floor(f * w * h);
7240 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7242 case Q3TCMOD_STRETCH:
7243 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7244 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7246 case Q3TCMOD_TRANSFORM:
7247 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7248 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7249 VectorSet(tcmat + 6, 0 , 0 , 1);
7250 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7251 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7253 case Q3TCMOD_TURBULENT:
7254 // this is handled in the RSurf_PrepareVertices function
7255 matrix = identitymatrix;
7259 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7262 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7264 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7265 char name[MAX_QPATH];
7266 skinframe_t *skinframe;
7267 unsigned char pixels[296*194];
7268 strlcpy(cache->name, skinname, sizeof(cache->name));
7269 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7270 if (developer_loading.integer)
7271 Con_Printf("loading %s\n", name);
7272 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7273 if (!skinframe || !skinframe->base)
7276 fs_offset_t filesize;
7278 f = FS_LoadFile(name, tempmempool, true, &filesize);
7281 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7282 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7286 cache->skinframe = skinframe;
7289 texture_t *R_GetCurrentTexture(texture_t *t)
7292 const entity_render_t *ent = rsurface.entity;
7293 dp_model_t *model = ent->model;
7294 q3shaderinfo_layer_tcmod_t *tcmod;
7296 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7297 return t->currentframe;
7298 t->update_lastrenderframe = r_textureframe;
7299 t->update_lastrenderentity = (void *)ent;
7301 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7302 t->camera_entity = ent->entitynumber;
7304 t->camera_entity = 0;
7306 // switch to an alternate material if this is a q1bsp animated material
7308 texture_t *texture = t;
7309 int s = rsurface.ent_skinnum;
7310 if ((unsigned int)s >= (unsigned int)model->numskins)
7312 if (model->skinscenes)
7314 if (model->skinscenes[s].framecount > 1)
7315 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7317 s = model->skinscenes[s].firstframe;
7320 t = t + s * model->num_surfaces;
7323 // use an alternate animation if the entity's frame is not 0,
7324 // and only if the texture has an alternate animation
7325 if (rsurface.ent_alttextures && t->anim_total[1])
7326 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7328 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7330 texture->currentframe = t;
7333 // update currentskinframe to be a qw skin or animation frame
7334 if (rsurface.ent_qwskin >= 0)
7336 i = rsurface.ent_qwskin;
7337 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7339 r_qwskincache_size = cl.maxclients;
7341 Mem_Free(r_qwskincache);
7342 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7344 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7345 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7346 t->currentskinframe = r_qwskincache[i].skinframe;
7347 if (t->currentskinframe == NULL)
7348 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7350 else if (t->numskinframes >= 2)
7351 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7352 if (t->backgroundnumskinframes >= 2)
7353 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7355 t->currentmaterialflags = t->basematerialflags;
7356 t->currentalpha = rsurface.colormod[3];
7357 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7358 t->currentalpha *= r_wateralpha.value;
7359 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7360 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7361 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7362 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7363 if (!(rsurface.ent_flags & RENDER_LIGHT))
7364 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7365 else if (FAKELIGHT_ENABLED)
7367 // no modellight if using fakelight for the map
7369 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7371 // pick a model lighting mode
7372 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7373 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7375 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7377 if (rsurface.ent_flags & RENDER_ADDITIVE)
7378 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7379 else if (t->currentalpha < 1)
7380 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7381 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7382 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7383 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7384 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7385 if (t->backgroundnumskinframes)
7386 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7387 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7389 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7390 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7393 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7394 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7395 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7397 // there is no tcmod
7398 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7400 t->currenttexmatrix = r_waterscrollmatrix;
7401 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7403 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7405 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7406 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7409 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7410 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7411 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7412 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7414 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7415 if (t->currentskinframe->qpixels)
7416 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7417 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7418 if (!t->basetexture)
7419 t->basetexture = r_texture_notexture;
7420 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7421 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7422 t->nmaptexture = t->currentskinframe->nmap;
7423 if (!t->nmaptexture)
7424 t->nmaptexture = r_texture_blanknormalmap;
7425 t->glosstexture = r_texture_black;
7426 t->glowtexture = t->currentskinframe->glow;
7427 t->fogtexture = t->currentskinframe->fog;
7428 t->reflectmasktexture = t->currentskinframe->reflect;
7429 if (t->backgroundnumskinframes)
7431 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7432 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7433 t->backgroundglosstexture = r_texture_black;
7434 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7435 if (!t->backgroundnmaptexture)
7436 t->backgroundnmaptexture = r_texture_blanknormalmap;
7440 t->backgroundbasetexture = r_texture_white;
7441 t->backgroundnmaptexture = r_texture_blanknormalmap;
7442 t->backgroundglosstexture = r_texture_black;
7443 t->backgroundglowtexture = NULL;
7445 t->specularpower = r_shadow_glossexponent.value;
7446 // TODO: store reference values for these in the texture?
7447 t->specularscale = 0;
7448 if (r_shadow_gloss.integer > 0)
7450 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7452 if (r_shadow_glossintensity.value > 0)
7454 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7455 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7456 t->specularscale = r_shadow_glossintensity.value;
7459 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7461 t->glosstexture = r_texture_white;
7462 t->backgroundglosstexture = r_texture_white;
7463 t->specularscale = r_shadow_gloss2intensity.value;
7464 t->specularpower = r_shadow_gloss2exponent.value;
7467 t->specularscale *= t->specularscalemod;
7468 t->specularpower *= t->specularpowermod;
7470 // lightmaps mode looks bad with dlights using actual texturing, so turn
7471 // off the colormap and glossmap, but leave the normalmap on as it still
7472 // accurately represents the shading involved
7473 if (gl_lightmaps.integer)
7475 t->basetexture = r_texture_grey128;
7476 t->pantstexture = r_texture_black;
7477 t->shirttexture = r_texture_black;
7478 t->nmaptexture = r_texture_blanknormalmap;
7479 t->glosstexture = r_texture_black;
7480 t->glowtexture = NULL;
7481 t->fogtexture = NULL;
7482 t->reflectmasktexture = NULL;
7483 t->backgroundbasetexture = NULL;
7484 t->backgroundnmaptexture = r_texture_blanknormalmap;
7485 t->backgroundglosstexture = r_texture_black;
7486 t->backgroundglowtexture = NULL;
7487 t->specularscale = 0;
7488 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7491 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7492 VectorClear(t->dlightcolor);
7493 t->currentnumlayers = 0;
7494 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7496 int blendfunc1, blendfunc2;
7498 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7500 blendfunc1 = GL_SRC_ALPHA;
7501 blendfunc2 = GL_ONE;
7503 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7505 blendfunc1 = GL_SRC_ALPHA;
7506 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7508 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7510 blendfunc1 = t->customblendfunc[0];
7511 blendfunc2 = t->customblendfunc[1];
7515 blendfunc1 = GL_ONE;
7516 blendfunc2 = GL_ZERO;
7518 // don't colormod evilblend textures
7519 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
7520 VectorSet(t->lightmapcolor, 1, 1, 1);
7521 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7522 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7524 // fullbright is not affected by r_refdef.lightmapintensity
7525 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]);
7526 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7527 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]);
7528 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7529 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]);
7533 vec3_t ambientcolor;
7535 // set the color tint used for lights affecting this surface
7536 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7538 // q3bsp has no lightmap updates, so the lightstylevalue that
7539 // would normally be baked into the lightmap must be
7540 // applied to the color
7541 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7542 if (model->type == mod_brushq3)
7543 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7544 colorscale *= r_refdef.lightmapintensity;
7545 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7546 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7547 // basic lit geometry
7548 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]);
7549 // add pants/shirt if needed
7550 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7551 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]);
7552 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7553 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]);
7554 // now add ambient passes if needed
7555 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7557 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]);
7558 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7559 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]);
7560 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7561 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]);
7564 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7565 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]);
7566 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7568 // if this is opaque use alpha blend which will darken the earlier
7571 // if this is an alpha blended material, all the earlier passes
7572 // were darkened by fog already, so we only need to add the fog
7573 // color ontop through the fog mask texture
7575 // if this is an additive blended material, all the earlier passes
7576 // were darkened by fog already, and we should not add fog color
7577 // (because the background was not darkened, there is no fog color
7578 // that was lost behind it).
7579 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]);
7583 return t->currentframe;
7586 rsurfacestate_t rsurface;
7588 void RSurf_ActiveWorldEntity(void)
7590 dp_model_t *model = r_refdef.scene.worldmodel;
7591 //if (rsurface.entity == r_refdef.scene.worldentity)
7593 rsurface.entity = r_refdef.scene.worldentity;
7594 rsurface.skeleton = NULL;
7595 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7596 rsurface.ent_skinnum = 0;
7597 rsurface.ent_qwskin = -1;
7598 rsurface.ent_shadertime = 0;
7599 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7600 rsurface.matrix = identitymatrix;
7601 rsurface.inversematrix = identitymatrix;
7602 rsurface.matrixscale = 1;
7603 rsurface.inversematrixscale = 1;
7604 R_EntityMatrix(&identitymatrix);
7605 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7606 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7607 rsurface.fograngerecip = r_refdef.fograngerecip;
7608 rsurface.fogheightfade = r_refdef.fogheightfade;
7609 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7610 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7611 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7612 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7613 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7614 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7615 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7616 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7617 rsurface.colormod[3] = 1;
7618 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);
7619 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7620 rsurface.frameblend[0].lerp = 1;
7621 rsurface.ent_alttextures = false;
7622 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7623 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7624 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7625 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7626 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7627 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7628 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7629 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7630 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7631 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7632 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7633 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7634 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7635 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7636 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7637 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7638 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7639 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7640 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7641 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7642 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7643 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7644 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7645 rsurface.modelelement3i = model->surfmesh.data_element3i;
7646 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7647 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7648 rsurface.modelelement3s = model->surfmesh.data_element3s;
7649 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7650 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7651 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7652 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7653 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7654 rsurface.modelsurfaces = model->data_surfaces;
7655 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7656 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7657 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7658 rsurface.modelgeneratedvertex = false;
7659 rsurface.batchgeneratedvertex = false;
7660 rsurface.batchfirstvertex = 0;
7661 rsurface.batchnumvertices = 0;
7662 rsurface.batchfirsttriangle = 0;
7663 rsurface.batchnumtriangles = 0;
7664 rsurface.batchvertex3f = NULL;
7665 rsurface.batchvertex3f_vertexbuffer = NULL;
7666 rsurface.batchvertex3f_bufferoffset = 0;
7667 rsurface.batchsvector3f = NULL;
7668 rsurface.batchsvector3f_vertexbuffer = NULL;
7669 rsurface.batchsvector3f_bufferoffset = 0;
7670 rsurface.batchtvector3f = NULL;
7671 rsurface.batchtvector3f_vertexbuffer = NULL;
7672 rsurface.batchtvector3f_bufferoffset = 0;
7673 rsurface.batchnormal3f = NULL;
7674 rsurface.batchnormal3f_vertexbuffer = NULL;
7675 rsurface.batchnormal3f_bufferoffset = 0;
7676 rsurface.batchlightmapcolor4f = NULL;
7677 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7678 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7679 rsurface.batchtexcoordtexture2f = NULL;
7680 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7681 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7682 rsurface.batchtexcoordlightmap2f = NULL;
7683 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7684 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7685 rsurface.batchvertexmesh = NULL;
7686 rsurface.batchvertexmeshbuffer = NULL;
7687 rsurface.batchvertex3fbuffer = NULL;
7688 rsurface.batchelement3i = NULL;
7689 rsurface.batchelement3i_indexbuffer = NULL;
7690 rsurface.batchelement3i_bufferoffset = 0;
7691 rsurface.batchelement3s = NULL;
7692 rsurface.batchelement3s_indexbuffer = NULL;
7693 rsurface.batchelement3s_bufferoffset = 0;
7694 rsurface.passcolor4f = NULL;
7695 rsurface.passcolor4f_vertexbuffer = NULL;
7696 rsurface.passcolor4f_bufferoffset = 0;
7699 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7701 dp_model_t *model = ent->model;
7702 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7704 rsurface.entity = (entity_render_t *)ent;
7705 rsurface.skeleton = ent->skeleton;
7706 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7707 rsurface.ent_skinnum = ent->skinnum;
7708 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;
7709 rsurface.ent_shadertime = ent->shadertime;
7710 rsurface.ent_flags = ent->flags;
7711 rsurface.matrix = ent->matrix;
7712 rsurface.inversematrix = ent->inversematrix;
7713 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7714 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7715 R_EntityMatrix(&rsurface.matrix);
7716 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7717 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7718 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7719 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7720 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7721 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7722 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7723 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7724 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7725 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7726 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7727 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7728 rsurface.colormod[3] = ent->alpha;
7729 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7730 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7731 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7732 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7733 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7734 if (ent->model->brush.submodel && !prepass)
7736 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7737 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7739 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7741 if (ent->animcache_vertex3f)
7743 rsurface.modelvertex3f = ent->animcache_vertex3f;
7744 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7745 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7746 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7747 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7748 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7749 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7751 else if (wanttangents)
7753 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7754 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7755 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7756 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7757 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7758 rsurface.modelvertexmesh = NULL;
7759 rsurface.modelvertexmeshbuffer = NULL;
7760 rsurface.modelvertex3fbuffer = NULL;
7762 else if (wantnormals)
7764 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7765 rsurface.modelsvector3f = NULL;
7766 rsurface.modeltvector3f = NULL;
7767 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7768 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7769 rsurface.modelvertexmesh = NULL;
7770 rsurface.modelvertexmeshbuffer = NULL;
7771 rsurface.modelvertex3fbuffer = NULL;
7775 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7776 rsurface.modelsvector3f = NULL;
7777 rsurface.modeltvector3f = NULL;
7778 rsurface.modelnormal3f = NULL;
7779 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7780 rsurface.modelvertexmesh = NULL;
7781 rsurface.modelvertexmeshbuffer = NULL;
7782 rsurface.modelvertex3fbuffer = NULL;
7784 rsurface.modelvertex3f_vertexbuffer = 0;
7785 rsurface.modelvertex3f_bufferoffset = 0;
7786 rsurface.modelsvector3f_vertexbuffer = 0;
7787 rsurface.modelsvector3f_bufferoffset = 0;
7788 rsurface.modeltvector3f_vertexbuffer = 0;
7789 rsurface.modeltvector3f_bufferoffset = 0;
7790 rsurface.modelnormal3f_vertexbuffer = 0;
7791 rsurface.modelnormal3f_bufferoffset = 0;
7792 rsurface.modelgeneratedvertex = true;
7796 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7797 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7798 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7799 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7800 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7801 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7802 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7803 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7804 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7805 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7806 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7807 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7808 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7809 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7810 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7811 rsurface.modelgeneratedvertex = false;
7813 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7814 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7815 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7816 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7817 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7818 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7819 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7820 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7821 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7822 rsurface.modelelement3i = model->surfmesh.data_element3i;
7823 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7824 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7825 rsurface.modelelement3s = model->surfmesh.data_element3s;
7826 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7827 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7828 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7829 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7830 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7831 rsurface.modelsurfaces = model->data_surfaces;
7832 rsurface.batchgeneratedvertex = false;
7833 rsurface.batchfirstvertex = 0;
7834 rsurface.batchnumvertices = 0;
7835 rsurface.batchfirsttriangle = 0;
7836 rsurface.batchnumtriangles = 0;
7837 rsurface.batchvertex3f = NULL;
7838 rsurface.batchvertex3f_vertexbuffer = NULL;
7839 rsurface.batchvertex3f_bufferoffset = 0;
7840 rsurface.batchsvector3f = NULL;
7841 rsurface.batchsvector3f_vertexbuffer = NULL;
7842 rsurface.batchsvector3f_bufferoffset = 0;
7843 rsurface.batchtvector3f = NULL;
7844 rsurface.batchtvector3f_vertexbuffer = NULL;
7845 rsurface.batchtvector3f_bufferoffset = 0;
7846 rsurface.batchnormal3f = NULL;
7847 rsurface.batchnormal3f_vertexbuffer = NULL;
7848 rsurface.batchnormal3f_bufferoffset = 0;
7849 rsurface.batchlightmapcolor4f = NULL;
7850 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7851 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7852 rsurface.batchtexcoordtexture2f = NULL;
7853 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7854 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7855 rsurface.batchtexcoordlightmap2f = NULL;
7856 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7857 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7858 rsurface.batchvertexmesh = NULL;
7859 rsurface.batchvertexmeshbuffer = NULL;
7860 rsurface.batchvertex3fbuffer = NULL;
7861 rsurface.batchelement3i = NULL;
7862 rsurface.batchelement3i_indexbuffer = NULL;
7863 rsurface.batchelement3i_bufferoffset = 0;
7864 rsurface.batchelement3s = NULL;
7865 rsurface.batchelement3s_indexbuffer = NULL;
7866 rsurface.batchelement3s_bufferoffset = 0;
7867 rsurface.passcolor4f = NULL;
7868 rsurface.passcolor4f_vertexbuffer = NULL;
7869 rsurface.passcolor4f_bufferoffset = 0;
7872 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)
7874 rsurface.entity = r_refdef.scene.worldentity;
7875 rsurface.skeleton = NULL;
7876 rsurface.ent_skinnum = 0;
7877 rsurface.ent_qwskin = -1;
7878 rsurface.ent_shadertime = shadertime;
7879 rsurface.ent_flags = entflags;
7880 rsurface.modelnumvertices = numvertices;
7881 rsurface.modelnumtriangles = numtriangles;
7882 rsurface.matrix = *matrix;
7883 rsurface.inversematrix = *inversematrix;
7884 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7885 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7886 R_EntityMatrix(&rsurface.matrix);
7887 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7888 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7889 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7890 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7891 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7892 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7893 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7894 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7895 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7896 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7897 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7898 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7899 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);
7900 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7901 rsurface.frameblend[0].lerp = 1;
7902 rsurface.ent_alttextures = false;
7903 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7904 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7907 rsurface.modelvertex3f = (float *)vertex3f;
7908 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7909 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7910 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7912 else if (wantnormals)
7914 rsurface.modelvertex3f = (float *)vertex3f;
7915 rsurface.modelsvector3f = NULL;
7916 rsurface.modeltvector3f = NULL;
7917 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7921 rsurface.modelvertex3f = (float *)vertex3f;
7922 rsurface.modelsvector3f = NULL;
7923 rsurface.modeltvector3f = NULL;
7924 rsurface.modelnormal3f = NULL;
7926 rsurface.modelvertexmesh = NULL;
7927 rsurface.modelvertexmeshbuffer = NULL;
7928 rsurface.modelvertex3fbuffer = NULL;
7929 rsurface.modelvertex3f_vertexbuffer = 0;
7930 rsurface.modelvertex3f_bufferoffset = 0;
7931 rsurface.modelsvector3f_vertexbuffer = 0;
7932 rsurface.modelsvector3f_bufferoffset = 0;
7933 rsurface.modeltvector3f_vertexbuffer = 0;
7934 rsurface.modeltvector3f_bufferoffset = 0;
7935 rsurface.modelnormal3f_vertexbuffer = 0;
7936 rsurface.modelnormal3f_bufferoffset = 0;
7937 rsurface.modelgeneratedvertex = true;
7938 rsurface.modellightmapcolor4f = (float *)color4f;
7939 rsurface.modellightmapcolor4f_vertexbuffer = 0;
7940 rsurface.modellightmapcolor4f_bufferoffset = 0;
7941 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
7942 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7943 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7944 rsurface.modeltexcoordlightmap2f = NULL;
7945 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7946 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7947 rsurface.modelelement3i = (int *)element3i;
7948 rsurface.modelelement3i_indexbuffer = NULL;
7949 rsurface.modelelement3i_bufferoffset = 0;
7950 rsurface.modelelement3s = (unsigned short *)element3s;
7951 rsurface.modelelement3s_indexbuffer = NULL;
7952 rsurface.modelelement3s_bufferoffset = 0;
7953 rsurface.modellightmapoffsets = NULL;
7954 rsurface.modelsurfaces = NULL;
7955 rsurface.batchgeneratedvertex = false;
7956 rsurface.batchfirstvertex = 0;
7957 rsurface.batchnumvertices = 0;
7958 rsurface.batchfirsttriangle = 0;
7959 rsurface.batchnumtriangles = 0;
7960 rsurface.batchvertex3f = NULL;
7961 rsurface.batchvertex3f_vertexbuffer = NULL;
7962 rsurface.batchvertex3f_bufferoffset = 0;
7963 rsurface.batchsvector3f = NULL;
7964 rsurface.batchsvector3f_vertexbuffer = NULL;
7965 rsurface.batchsvector3f_bufferoffset = 0;
7966 rsurface.batchtvector3f = NULL;
7967 rsurface.batchtvector3f_vertexbuffer = NULL;
7968 rsurface.batchtvector3f_bufferoffset = 0;
7969 rsurface.batchnormal3f = NULL;
7970 rsurface.batchnormal3f_vertexbuffer = NULL;
7971 rsurface.batchnormal3f_bufferoffset = 0;
7972 rsurface.batchlightmapcolor4f = NULL;
7973 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7974 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7975 rsurface.batchtexcoordtexture2f = NULL;
7976 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7977 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7978 rsurface.batchtexcoordlightmap2f = NULL;
7979 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7980 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7981 rsurface.batchvertexmesh = NULL;
7982 rsurface.batchvertexmeshbuffer = NULL;
7983 rsurface.batchvertex3fbuffer = NULL;
7984 rsurface.batchelement3i = NULL;
7985 rsurface.batchelement3i_indexbuffer = NULL;
7986 rsurface.batchelement3i_bufferoffset = 0;
7987 rsurface.batchelement3s = NULL;
7988 rsurface.batchelement3s_indexbuffer = NULL;
7989 rsurface.batchelement3s_bufferoffset = 0;
7990 rsurface.passcolor4f = NULL;
7991 rsurface.passcolor4f_vertexbuffer = NULL;
7992 rsurface.passcolor4f_bufferoffset = 0;
7994 if (rsurface.modelnumvertices && rsurface.modelelement3i)
7996 if ((wantnormals || wanttangents) && !normal3f)
7998 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7999 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8001 if (wanttangents && !svector3f)
8003 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8004 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8005 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8010 float RSurf_FogPoint(const float *v)
8012 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8013 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8014 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8015 float FogHeightFade = r_refdef.fogheightfade;
8017 unsigned int fogmasktableindex;
8018 if (r_refdef.fogplaneviewabove)
8019 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8021 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8022 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8023 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8026 float RSurf_FogVertex(const float *v)
8028 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8029 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8030 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8031 float FogHeightFade = rsurface.fogheightfade;
8033 unsigned int fogmasktableindex;
8034 if (r_refdef.fogplaneviewabove)
8035 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8037 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8038 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8039 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8042 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8045 for (i = 0;i < numelements;i++)
8046 outelement3i[i] = inelement3i[i] + adjust;
8049 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8050 extern cvar_t gl_vbo;
8051 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8059 int surfacefirsttriangle;
8060 int surfacenumtriangles;
8061 int surfacefirstvertex;
8062 int surfaceendvertex;
8063 int surfacenumvertices;
8064 int batchnumvertices;
8065 int batchnumtriangles;
8069 qboolean dynamicvertex;
8073 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8075 q3shaderinfo_deform_t *deform;
8076 const msurface_t *surface, *firstsurface;
8077 r_vertexmesh_t *vertexmesh;
8078 if (!texturenumsurfaces)
8080 // find vertex range of this surface batch
8082 firstsurface = texturesurfacelist[0];
8083 firsttriangle = firstsurface->num_firsttriangle;
8084 batchnumvertices = 0;
8085 batchnumtriangles = 0;
8086 firstvertex = endvertex = firstsurface->num_firstvertex;
8087 for (i = 0;i < texturenumsurfaces;i++)
8089 surface = texturesurfacelist[i];
8090 if (surface != firstsurface + i)
8092 surfacefirstvertex = surface->num_firstvertex;
8093 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8094 surfacenumvertices = surface->num_vertices;
8095 surfacenumtriangles = surface->num_triangles;
8096 if (firstvertex > surfacefirstvertex)
8097 firstvertex = surfacefirstvertex;
8098 if (endvertex < surfaceendvertex)
8099 endvertex = surfaceendvertex;
8100 batchnumvertices += surfacenumvertices;
8101 batchnumtriangles += surfacenumtriangles;
8104 // we now know the vertex range used, and if there are any gaps in it
8105 rsurface.batchfirstvertex = firstvertex;
8106 rsurface.batchnumvertices = endvertex - firstvertex;
8107 rsurface.batchfirsttriangle = firsttriangle;
8108 rsurface.batchnumtriangles = batchnumtriangles;
8110 // this variable holds flags for which properties have been updated that
8111 // may require regenerating vertexmesh array...
8114 // check if any dynamic vertex processing must occur
8115 dynamicvertex = false;
8117 // if there is a chance of animated vertex colors, it's a dynamic batch
8118 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8120 dynamicvertex = true;
8121 batchneed |= BATCHNEED_NOGAPS;
8122 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8125 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8127 switch (deform->deform)
8130 case Q3DEFORM_PROJECTIONSHADOW:
8131 case Q3DEFORM_TEXT0:
8132 case Q3DEFORM_TEXT1:
8133 case Q3DEFORM_TEXT2:
8134 case Q3DEFORM_TEXT3:
8135 case Q3DEFORM_TEXT4:
8136 case Q3DEFORM_TEXT5:
8137 case Q3DEFORM_TEXT6:
8138 case Q3DEFORM_TEXT7:
8141 case Q3DEFORM_AUTOSPRITE:
8142 dynamicvertex = true;
8143 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8144 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8146 case Q3DEFORM_AUTOSPRITE2:
8147 dynamicvertex = true;
8148 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8149 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8151 case Q3DEFORM_NORMAL:
8152 dynamicvertex = true;
8153 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8154 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8157 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8158 break; // if wavefunc is a nop, ignore this transform
8159 dynamicvertex = true;
8160 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8161 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8163 case Q3DEFORM_BULGE:
8164 dynamicvertex = true;
8165 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8166 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8169 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8170 break; // if wavefunc is a nop, ignore this transform
8171 dynamicvertex = true;
8172 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8173 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8177 switch(rsurface.texture->tcgen.tcgen)
8180 case Q3TCGEN_TEXTURE:
8182 case Q3TCGEN_LIGHTMAP:
8183 dynamicvertex = true;
8184 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8185 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8187 case Q3TCGEN_VECTOR:
8188 dynamicvertex = true;
8189 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8190 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8192 case Q3TCGEN_ENVIRONMENT:
8193 dynamicvertex = true;
8194 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8195 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8198 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8200 dynamicvertex = true;
8201 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8202 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8205 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8207 dynamicvertex = true;
8208 batchneed |= BATCHNEED_NOGAPS;
8209 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8212 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8214 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8215 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8216 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8217 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8218 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8219 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8220 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8223 // when the model data has no vertex buffer (dynamic mesh), we need to
8225 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8226 batchneed |= BATCHNEED_NOGAPS;
8228 // if needsupdate, we have to do a dynamic vertex batch for sure
8229 if (needsupdate & batchneed)
8230 dynamicvertex = true;
8232 // see if we need to build vertexmesh from arrays
8233 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8234 dynamicvertex = true;
8236 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8237 // also some drivers strongly dislike firstvertex
8238 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8239 dynamicvertex = true;
8241 rsurface.batchvertex3f = rsurface.modelvertex3f;
8242 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8243 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8244 rsurface.batchsvector3f = rsurface.modelsvector3f;
8245 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8246 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8247 rsurface.batchtvector3f = rsurface.modeltvector3f;
8248 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8249 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8250 rsurface.batchnormal3f = rsurface.modelnormal3f;
8251 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8252 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8253 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8254 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8255 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8256 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8257 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8258 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8259 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8260 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8261 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8262 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8263 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8264 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8265 rsurface.batchelement3i = rsurface.modelelement3i;
8266 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8267 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8268 rsurface.batchelement3s = rsurface.modelelement3s;
8269 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8270 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8272 // if any dynamic vertex processing has to occur in software, we copy the
8273 // entire surface list together before processing to rebase the vertices
8274 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8276 // if any gaps exist and we do not have a static vertex buffer, we have to
8277 // copy the surface list together to avoid wasting upload bandwidth on the
8278 // vertices in the gaps.
8280 // if gaps exist and we have a static vertex buffer, we still have to
8281 // combine the index buffer ranges into one dynamic index buffer.
8283 // in all cases we end up with data that can be drawn in one call.
8287 // static vertex data, just set pointers...
8288 rsurface.batchgeneratedvertex = false;
8289 // if there are gaps, we want to build a combined index buffer,
8290 // otherwise use the original static buffer with an appropriate offset
8293 // build a new triangle elements array for this batch
8294 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8295 rsurface.batchfirsttriangle = 0;
8297 for (i = 0;i < texturenumsurfaces;i++)
8299 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8300 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8301 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8302 numtriangles += surfacenumtriangles;
8304 rsurface.batchelement3i_indexbuffer = NULL;
8305 rsurface.batchelement3i_bufferoffset = 0;
8306 rsurface.batchelement3s = NULL;
8307 rsurface.batchelement3s_indexbuffer = NULL;
8308 rsurface.batchelement3s_bufferoffset = 0;
8309 if (endvertex <= 65536)
8311 // make a 16bit (unsigned short) index array if possible
8312 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8313 for (i = 0;i < numtriangles*3;i++)
8314 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8320 // something needs software processing, do it for real...
8321 // we only directly handle separate array data in this case and then
8322 // generate interleaved data if needed...
8323 rsurface.batchgeneratedvertex = true;
8325 // now copy the vertex data into a combined array and make an index array
8326 // (this is what Quake3 does all the time)
8327 //if (gaps || rsurface.batchfirstvertex)
8329 rsurface.batchvertex3fbuffer = NULL;
8330 rsurface.batchvertexmesh = NULL;
8331 rsurface.batchvertexmeshbuffer = NULL;
8332 rsurface.batchvertex3f = NULL;
8333 rsurface.batchvertex3f_vertexbuffer = NULL;
8334 rsurface.batchvertex3f_bufferoffset = 0;
8335 rsurface.batchsvector3f = NULL;
8336 rsurface.batchsvector3f_vertexbuffer = NULL;
8337 rsurface.batchsvector3f_bufferoffset = 0;
8338 rsurface.batchtvector3f = NULL;
8339 rsurface.batchtvector3f_vertexbuffer = NULL;
8340 rsurface.batchtvector3f_bufferoffset = 0;
8341 rsurface.batchnormal3f = NULL;
8342 rsurface.batchnormal3f_vertexbuffer = NULL;
8343 rsurface.batchnormal3f_bufferoffset = 0;
8344 rsurface.batchlightmapcolor4f = NULL;
8345 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8346 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8347 rsurface.batchtexcoordtexture2f = NULL;
8348 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8349 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8350 rsurface.batchtexcoordlightmap2f = NULL;
8351 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8352 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8353 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8354 rsurface.batchelement3i_indexbuffer = NULL;
8355 rsurface.batchelement3i_bufferoffset = 0;
8356 rsurface.batchelement3s = NULL;
8357 rsurface.batchelement3s_indexbuffer = NULL;
8358 rsurface.batchelement3s_bufferoffset = 0;
8359 // we'll only be setting up certain arrays as needed
8360 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8361 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8362 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8363 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8364 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8365 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8366 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8368 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8369 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8371 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8372 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8373 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8374 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8375 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8376 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8379 for (i = 0;i < texturenumsurfaces;i++)
8381 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8382 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8383 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8384 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8385 // copy only the data requested
8386 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8387 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8388 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8390 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8391 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8392 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8393 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8394 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8396 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8397 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8399 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8400 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8401 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8402 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8403 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8404 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8406 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8407 numvertices += surfacenumvertices;
8408 numtriangles += surfacenumtriangles;
8411 // generate a 16bit index array as well if possible
8412 // (in general, dynamic batches fit)
8413 if (numvertices <= 65536)
8415 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8416 for (i = 0;i < numtriangles*3;i++)
8417 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8420 // since we've copied everything, the batch now starts at 0
8421 rsurface.batchfirstvertex = 0;
8422 rsurface.batchnumvertices = batchnumvertices;
8423 rsurface.batchfirsttriangle = 0;
8424 rsurface.batchnumtriangles = batchnumtriangles;
8427 // q1bsp surfaces rendered in vertex color mode have to have colors
8428 // calculated based on lightstyles
8429 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8431 // generate color arrays for the surfaces in this list
8436 const unsigned char *lm;
8437 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8438 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8439 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8441 for (i = 0;i < texturenumsurfaces;i++)
8443 surface = texturesurfacelist[i];
8444 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8445 surfacenumvertices = surface->num_vertices;
8446 if (surface->lightmapinfo->samples)
8448 for (j = 0;j < surfacenumvertices;j++)
8450 lm = surface->lightmapinfo->samples + offsets[j];
8451 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8452 VectorScale(lm, scale, c);
8453 if (surface->lightmapinfo->styles[1] != 255)
8455 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8457 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8458 VectorMA(c, scale, lm, c);
8459 if (surface->lightmapinfo->styles[2] != 255)
8462 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8463 VectorMA(c, scale, lm, c);
8464 if (surface->lightmapinfo->styles[3] != 255)
8467 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8468 VectorMA(c, scale, lm, c);
8475 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);
8481 for (j = 0;j < surfacenumvertices;j++)
8483 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8490 // if vertices are deformed (sprite flares and things in maps, possibly
8491 // water waves, bulges and other deformations), modify the copied vertices
8493 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8495 switch (deform->deform)
8498 case Q3DEFORM_PROJECTIONSHADOW:
8499 case Q3DEFORM_TEXT0:
8500 case Q3DEFORM_TEXT1:
8501 case Q3DEFORM_TEXT2:
8502 case Q3DEFORM_TEXT3:
8503 case Q3DEFORM_TEXT4:
8504 case Q3DEFORM_TEXT5:
8505 case Q3DEFORM_TEXT6:
8506 case Q3DEFORM_TEXT7:
8509 case Q3DEFORM_AUTOSPRITE:
8510 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8511 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8512 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8513 VectorNormalize(newforward);
8514 VectorNormalize(newright);
8515 VectorNormalize(newup);
8516 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8517 // rsurface.batchvertex3f_vertexbuffer = NULL;
8518 // rsurface.batchvertex3f_bufferoffset = 0;
8519 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8520 // rsurface.batchsvector3f_vertexbuffer = NULL;
8521 // rsurface.batchsvector3f_bufferoffset = 0;
8522 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8523 // rsurface.batchtvector3f_vertexbuffer = NULL;
8524 // rsurface.batchtvector3f_bufferoffset = 0;
8525 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8526 // rsurface.batchnormal3f_vertexbuffer = NULL;
8527 // rsurface.batchnormal3f_bufferoffset = 0;
8528 // a single autosprite surface can contain multiple sprites...
8529 for (j = 0;j < batchnumvertices - 3;j += 4)
8531 VectorClear(center);
8532 for (i = 0;i < 4;i++)
8533 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8534 VectorScale(center, 0.25f, center);
8535 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8536 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8537 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8538 for (i = 0;i < 4;i++)
8540 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8541 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8544 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8545 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8546 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);
8548 case Q3DEFORM_AUTOSPRITE2:
8549 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8550 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8551 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8552 VectorNormalize(newforward);
8553 VectorNormalize(newright);
8554 VectorNormalize(newup);
8555 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8556 // rsurface.batchvertex3f_vertexbuffer = NULL;
8557 // rsurface.batchvertex3f_bufferoffset = 0;
8559 const float *v1, *v2;
8569 memset(shortest, 0, sizeof(shortest));
8570 // a single autosprite surface can contain multiple sprites...
8571 for (j = 0;j < batchnumvertices - 3;j += 4)
8573 VectorClear(center);
8574 for (i = 0;i < 4;i++)
8575 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8576 VectorScale(center, 0.25f, center);
8577 // find the two shortest edges, then use them to define the
8578 // axis vectors for rotating around the central axis
8579 for (i = 0;i < 6;i++)
8581 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8582 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8583 l = VectorDistance2(v1, v2);
8584 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8586 l += (1.0f / 1024.0f);
8587 if (shortest[0].length2 > l || i == 0)
8589 shortest[1] = shortest[0];
8590 shortest[0].length2 = l;
8591 shortest[0].v1 = v1;
8592 shortest[0].v2 = v2;
8594 else if (shortest[1].length2 > l || i == 1)
8596 shortest[1].length2 = l;
8597 shortest[1].v1 = v1;
8598 shortest[1].v2 = v2;
8601 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8602 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8603 // this calculates the right vector from the shortest edge
8604 // and the up vector from the edge midpoints
8605 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8606 VectorNormalize(right);
8607 VectorSubtract(end, start, up);
8608 VectorNormalize(up);
8609 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8610 VectorSubtract(rsurface.localvieworigin, center, forward);
8611 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8612 VectorNegate(forward, forward);
8613 VectorReflect(forward, 0, up, forward);
8614 VectorNormalize(forward);
8615 CrossProduct(up, forward, newright);
8616 VectorNormalize(newright);
8617 // rotate the quad around the up axis vector, this is made
8618 // especially easy by the fact we know the quad is flat,
8619 // so we only have to subtract the center position and
8620 // measure distance along the right vector, and then
8621 // multiply that by the newright vector and add back the
8623 // we also need to subtract the old position to undo the
8624 // displacement from the center, which we do with a
8625 // DotProduct, the subtraction/addition of center is also
8626 // optimized into DotProducts here
8627 l = DotProduct(right, center);
8628 for (i = 0;i < 4;i++)
8630 v1 = rsurface.batchvertex3f + 3*(j+i);
8631 f = DotProduct(right, v1) - l;
8632 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8636 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8638 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8639 // rsurface.batchnormal3f_vertexbuffer = NULL;
8640 // rsurface.batchnormal3f_bufferoffset = 0;
8641 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8643 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8645 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8646 // rsurface.batchsvector3f_vertexbuffer = NULL;
8647 // rsurface.batchsvector3f_bufferoffset = 0;
8648 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8649 // rsurface.batchtvector3f_vertexbuffer = NULL;
8650 // rsurface.batchtvector3f_bufferoffset = 0;
8651 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);
8654 case Q3DEFORM_NORMAL:
8655 // deform the normals to make reflections wavey
8656 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8657 rsurface.batchnormal3f_vertexbuffer = NULL;
8658 rsurface.batchnormal3f_bufferoffset = 0;
8659 for (j = 0;j < batchnumvertices;j++)
8662 float *normal = rsurface.batchnormal3f + 3*j;
8663 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8664 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8665 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]);
8666 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]);
8667 VectorNormalize(normal);
8669 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8671 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8672 // rsurface.batchsvector3f_vertexbuffer = NULL;
8673 // rsurface.batchsvector3f_bufferoffset = 0;
8674 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8675 // rsurface.batchtvector3f_vertexbuffer = NULL;
8676 // rsurface.batchtvector3f_bufferoffset = 0;
8677 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);
8681 // deform vertex array to make wavey water and flags and such
8682 waveparms[0] = deform->waveparms[0];
8683 waveparms[1] = deform->waveparms[1];
8684 waveparms[2] = deform->waveparms[2];
8685 waveparms[3] = deform->waveparms[3];
8686 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8687 break; // if wavefunc is a nop, don't make a dynamic vertex array
8688 // this is how a divisor of vertex influence on deformation
8689 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8690 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8691 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8692 // rsurface.batchvertex3f_vertexbuffer = NULL;
8693 // rsurface.batchvertex3f_bufferoffset = 0;
8694 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8695 // rsurface.batchnormal3f_vertexbuffer = NULL;
8696 // rsurface.batchnormal3f_bufferoffset = 0;
8697 for (j = 0;j < batchnumvertices;j++)
8699 // if the wavefunc depends on time, evaluate it per-vertex
8702 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8703 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8705 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8707 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8708 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8709 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8711 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8712 // rsurface.batchsvector3f_vertexbuffer = NULL;
8713 // rsurface.batchsvector3f_bufferoffset = 0;
8714 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8715 // rsurface.batchtvector3f_vertexbuffer = NULL;
8716 // rsurface.batchtvector3f_bufferoffset = 0;
8717 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);
8720 case Q3DEFORM_BULGE:
8721 // deform vertex array to make the surface have moving bulges
8722 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8723 // rsurface.batchvertex3f_vertexbuffer = NULL;
8724 // rsurface.batchvertex3f_bufferoffset = 0;
8725 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8726 // rsurface.batchnormal3f_vertexbuffer = NULL;
8727 // rsurface.batchnormal3f_bufferoffset = 0;
8728 for (j = 0;j < batchnumvertices;j++)
8730 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8731 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8733 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8734 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8735 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8737 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8738 // rsurface.batchsvector3f_vertexbuffer = NULL;
8739 // rsurface.batchsvector3f_bufferoffset = 0;
8740 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8741 // rsurface.batchtvector3f_vertexbuffer = NULL;
8742 // rsurface.batchtvector3f_bufferoffset = 0;
8743 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);
8747 // deform vertex array
8748 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8749 break; // if wavefunc is a nop, don't make a dynamic vertex array
8750 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8751 VectorScale(deform->parms, scale, waveparms);
8752 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8753 // rsurface.batchvertex3f_vertexbuffer = NULL;
8754 // rsurface.batchvertex3f_bufferoffset = 0;
8755 for (j = 0;j < batchnumvertices;j++)
8756 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8761 // generate texcoords based on the chosen texcoord source
8762 switch(rsurface.texture->tcgen.tcgen)
8765 case Q3TCGEN_TEXTURE:
8767 case Q3TCGEN_LIGHTMAP:
8768 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8769 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8770 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8771 if (rsurface.batchtexcoordlightmap2f)
8772 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8774 case Q3TCGEN_VECTOR:
8775 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8776 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8777 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8778 for (j = 0;j < batchnumvertices;j++)
8780 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8781 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8784 case Q3TCGEN_ENVIRONMENT:
8785 // make environment reflections using a spheremap
8786 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8787 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8788 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8789 for (j = 0;j < batchnumvertices;j++)
8791 // identical to Q3A's method, but executed in worldspace so
8792 // carried models can be shiny too
8794 float viewer[3], d, reflected[3], worldreflected[3];
8796 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8797 // VectorNormalize(viewer);
8799 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8801 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8802 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8803 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8804 // note: this is proportinal to viewer, so we can normalize later
8806 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8807 VectorNormalize(worldreflected);
8809 // note: this sphere map only uses world x and z!
8810 // so positive and negative y will LOOK THE SAME.
8811 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8812 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8816 // the only tcmod that needs software vertex processing is turbulent, so
8817 // check for it here and apply the changes if needed
8818 // and we only support that as the first one
8819 // (handling a mixture of turbulent and other tcmods would be problematic
8820 // without punting it entirely to a software path)
8821 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8823 amplitude = rsurface.texture->tcmods[0].parms[1];
8824 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8825 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8826 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8827 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8828 for (j = 0;j < batchnumvertices;j++)
8830 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);
8831 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8835 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8837 // convert the modified arrays to vertex structs
8838 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8839 // rsurface.batchvertexmeshbuffer = NULL;
8840 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8841 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8842 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8843 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8844 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8845 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8846 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8848 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8850 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8851 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8854 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8855 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8856 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8857 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8858 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8859 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8860 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8861 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8862 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8866 void RSurf_DrawBatch(void)
8868 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8869 // through the pipeline, killing it earlier in the pipeline would have
8870 // per-surface overhead rather than per-batch overhead, so it's best to
8871 // reject it here, before it hits glDraw.
8872 if (rsurface.batchnumtriangles == 0)
8875 // batch debugging code
8876 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8882 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8883 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8886 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8888 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8890 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8891 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);
8898 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);
8901 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8903 // pick the closest matching water plane
8904 int planeindex, vertexindex, bestplaneindex = -1;
8908 r_waterstate_waterplane_t *p;
8909 qboolean prepared = false;
8911 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8913 if(p->camera_entity != rsurface.texture->camera_entity)
8918 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8920 if(rsurface.batchnumvertices == 0)
8923 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8925 Matrix4x4_Transform(&rsurface.matrix, v, vert);
8926 d += fabs(PlaneDiff(vert, &p->plane));
8928 if (bestd > d || bestplaneindex < 0)
8931 bestplaneindex = planeindex;
8934 return bestplaneindex;
8935 // NOTE: this MAY return a totally unrelated water plane; we can ignore
8936 // this situation though, as it might be better to render single larger
8937 // batches with useless stuff (backface culled for example) than to
8938 // render multiple smaller batches
8941 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8944 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8945 rsurface.passcolor4f_vertexbuffer = 0;
8946 rsurface.passcolor4f_bufferoffset = 0;
8947 for (i = 0;i < rsurface.batchnumvertices;i++)
8948 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8951 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8958 if (rsurface.passcolor4f)
8960 // generate color arrays
8961 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8962 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8963 rsurface.passcolor4f_vertexbuffer = 0;
8964 rsurface.passcolor4f_bufferoffset = 0;
8965 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)
8967 f = RSurf_FogVertex(v);
8976 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8977 rsurface.passcolor4f_vertexbuffer = 0;
8978 rsurface.passcolor4f_bufferoffset = 0;
8979 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8981 f = RSurf_FogVertex(v);
8990 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8997 if (!rsurface.passcolor4f)
8999 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9000 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9001 rsurface.passcolor4f_vertexbuffer = 0;
9002 rsurface.passcolor4f_bufferoffset = 0;
9003 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)
9005 f = RSurf_FogVertex(v);
9006 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9007 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9008 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9013 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9018 if (!rsurface.passcolor4f)
9020 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9021 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9022 rsurface.passcolor4f_vertexbuffer = 0;
9023 rsurface.passcolor4f_bufferoffset = 0;
9024 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9033 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9038 if (!rsurface.passcolor4f)
9040 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9041 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9042 rsurface.passcolor4f_vertexbuffer = 0;
9043 rsurface.passcolor4f_bufferoffset = 0;
9044 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9046 c2[0] = c[0] + r_refdef.scene.ambient;
9047 c2[1] = c[1] + r_refdef.scene.ambient;
9048 c2[2] = c[2] + r_refdef.scene.ambient;
9053 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9056 rsurface.passcolor4f = NULL;
9057 rsurface.passcolor4f_vertexbuffer = 0;
9058 rsurface.passcolor4f_bufferoffset = 0;
9059 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9060 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9061 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9062 GL_Color(r, g, b, a);
9063 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9067 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9069 // TODO: optimize applyfog && applycolor case
9070 // just apply fog if necessary, and tint the fog color array if necessary
9071 rsurface.passcolor4f = NULL;
9072 rsurface.passcolor4f_vertexbuffer = 0;
9073 rsurface.passcolor4f_bufferoffset = 0;
9074 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9075 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9076 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9077 GL_Color(r, g, b, a);
9081 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9084 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9085 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9086 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9087 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9088 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9089 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9090 GL_Color(r, g, b, a);
9094 static void RSurf_DrawBatch_GL11_ClampColor(void)
9099 if (!rsurface.passcolor4f)
9101 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9103 c2[0] = bound(0.0f, c1[0], 1.0f);
9104 c2[1] = bound(0.0f, c1[1], 1.0f);
9105 c2[2] = bound(0.0f, c1[2], 1.0f);
9106 c2[3] = bound(0.0f, c1[3], 1.0f);
9110 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9120 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9121 rsurface.passcolor4f_vertexbuffer = 0;
9122 rsurface.passcolor4f_bufferoffset = 0;
9123 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)
9125 f = -DotProduct(r_refdef.view.forward, n);
9127 f = f * 0.85 + 0.15; // work around so stuff won't get black
9128 f *= r_refdef.lightmapintensity;
9129 Vector4Set(c, f, f, f, 1);
9133 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9135 RSurf_DrawBatch_GL11_ApplyFakeLight();
9136 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9137 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9138 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9139 GL_Color(r, g, b, a);
9143 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9151 vec3_t ambientcolor;
9152 vec3_t diffusecolor;
9156 VectorCopy(rsurface.modellight_lightdir, lightdir);
9157 f = 0.5f * r_refdef.lightmapintensity;
9158 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9159 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9160 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9161 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9162 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9163 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9165 if (VectorLength2(diffusecolor) > 0)
9167 // q3-style directional shading
9168 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9169 rsurface.passcolor4f_vertexbuffer = 0;
9170 rsurface.passcolor4f_bufferoffset = 0;
9171 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)
9173 if ((f = DotProduct(n, lightdir)) > 0)
9174 VectorMA(ambientcolor, f, diffusecolor, c);
9176 VectorCopy(ambientcolor, c);
9183 *applycolor = false;
9187 *r = ambientcolor[0];
9188 *g = ambientcolor[1];
9189 *b = ambientcolor[2];
9190 rsurface.passcolor4f = NULL;
9191 rsurface.passcolor4f_vertexbuffer = 0;
9192 rsurface.passcolor4f_bufferoffset = 0;
9196 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9198 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9199 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9200 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9201 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9202 GL_Color(r, g, b, a);
9206 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9212 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9214 f = 1 - RSurf_FogVertex(v);
9222 void RSurf_SetupDepthAndCulling(void)
9224 // submodels are biased to avoid z-fighting with world surfaces that they
9225 // may be exactly overlapping (avoids z-fighting artifacts on certain
9226 // doors and things in Quake maps)
9227 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9228 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9229 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9230 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9233 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9235 // transparent sky would be ridiculous
9236 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9238 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9239 skyrenderlater = true;
9240 RSurf_SetupDepthAndCulling();
9242 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9243 // skymasking on them, and Quake3 never did sky masking (unlike
9244 // software Quake and software Quake2), so disable the sky masking
9245 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9246 // and skymasking also looks very bad when noclipping outside the
9247 // level, so don't use it then either.
9248 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9250 R_Mesh_ResetTextureState();
9251 if (skyrendermasked)
9253 R_SetupShader_DepthOrShadow();
9254 // depth-only (masking)
9255 GL_ColorMask(0,0,0,0);
9256 // just to make sure that braindead drivers don't draw
9257 // anything despite that colormask...
9258 GL_BlendFunc(GL_ZERO, GL_ONE);
9259 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9260 if (rsurface.batchvertex3fbuffer)
9261 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9263 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9267 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9269 GL_BlendFunc(GL_ONE, GL_ZERO);
9270 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9271 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9272 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9275 if (skyrendermasked)
9276 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9278 R_Mesh_ResetTextureState();
9279 GL_Color(1, 1, 1, 1);
9282 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9283 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9284 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9286 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9290 // render screenspace normalmap to texture
9292 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9297 // bind lightmap texture
9299 // water/refraction/reflection/camera surfaces have to be handled specially
9300 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9302 int start, end, startplaneindex;
9303 for (start = 0;start < texturenumsurfaces;start = end)
9305 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9306 if(startplaneindex < 0)
9308 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9309 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9313 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9315 // now that we have a batch using the same planeindex, render it
9316 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9318 // render water or distortion background
9320 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));
9322 // blend surface on top
9323 GL_DepthMask(false);
9324 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9327 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9329 // render surface with reflection texture as input
9330 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9331 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));
9338 // render surface batch normally
9339 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9340 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9344 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9346 // OpenGL 1.3 path - anything not completely ancient
9347 qboolean applycolor;
9350 const texturelayer_t *layer;
9351 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);
9352 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9354 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9357 int layertexrgbscale;
9358 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9360 if (layerindex == 0)
9364 GL_AlphaTest(false);
9365 GL_DepthFunc(GL_EQUAL);
9368 GL_DepthMask(layer->depthmask && writedepth);
9369 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9370 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9372 layertexrgbscale = 4;
9373 VectorScale(layer->color, 0.25f, layercolor);
9375 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9377 layertexrgbscale = 2;
9378 VectorScale(layer->color, 0.5f, layercolor);
9382 layertexrgbscale = 1;
9383 VectorScale(layer->color, 1.0f, layercolor);
9385 layercolor[3] = layer->color[3];
9386 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9387 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9388 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9389 switch (layer->type)
9391 case TEXTURELAYERTYPE_LITTEXTURE:
9392 // single-pass lightmapped texture with 2x rgbscale
9393 R_Mesh_TexBind(0, r_texture_white);
9394 R_Mesh_TexMatrix(0, NULL);
9395 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9396 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9397 R_Mesh_TexBind(1, layer->texture);
9398 R_Mesh_TexMatrix(1, &layer->texmatrix);
9399 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9400 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9401 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9402 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9403 else if (FAKELIGHT_ENABLED)
9404 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9405 else if (rsurface.uselightmaptexture)
9406 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9408 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9410 case TEXTURELAYERTYPE_TEXTURE:
9411 // singletexture unlit texture with transparency support
9412 R_Mesh_TexBind(0, layer->texture);
9413 R_Mesh_TexMatrix(0, &layer->texmatrix);
9414 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9415 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9416 R_Mesh_TexBind(1, 0);
9417 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9418 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9420 case TEXTURELAYERTYPE_FOG:
9421 // singletexture fogging
9424 R_Mesh_TexBind(0, layer->texture);
9425 R_Mesh_TexMatrix(0, &layer->texmatrix);
9426 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9427 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9431 R_Mesh_TexBind(0, 0);
9432 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9434 R_Mesh_TexBind(1, 0);
9435 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9436 // generate a color array for the fog pass
9437 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9438 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9442 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9445 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9447 GL_DepthFunc(GL_LEQUAL);
9448 GL_AlphaTest(false);
9452 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9454 // OpenGL 1.1 - crusty old voodoo path
9457 const texturelayer_t *layer;
9458 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);
9459 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9461 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9463 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9465 if (layerindex == 0)
9469 GL_AlphaTest(false);
9470 GL_DepthFunc(GL_EQUAL);
9473 GL_DepthMask(layer->depthmask && writedepth);
9474 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9475 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9476 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9477 switch (layer->type)
9479 case TEXTURELAYERTYPE_LITTEXTURE:
9480 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9482 // two-pass lit texture with 2x rgbscale
9483 // first the lightmap pass
9484 R_Mesh_TexBind(0, r_texture_white);
9485 R_Mesh_TexMatrix(0, NULL);
9486 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9487 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9488 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9489 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9490 else if (FAKELIGHT_ENABLED)
9491 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9492 else if (rsurface.uselightmaptexture)
9493 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9495 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9496 // then apply the texture to it
9497 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9498 R_Mesh_TexBind(0, layer->texture);
9499 R_Mesh_TexMatrix(0, &layer->texmatrix);
9500 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9501 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9502 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);
9506 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9507 R_Mesh_TexBind(0, layer->texture);
9508 R_Mesh_TexMatrix(0, &layer->texmatrix);
9509 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9510 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9511 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9512 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);
9514 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);
9517 case TEXTURELAYERTYPE_TEXTURE:
9518 // singletexture unlit texture with transparency support
9519 R_Mesh_TexBind(0, layer->texture);
9520 R_Mesh_TexMatrix(0, &layer->texmatrix);
9521 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9522 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9523 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);
9525 case TEXTURELAYERTYPE_FOG:
9526 // singletexture fogging
9529 R_Mesh_TexBind(0, layer->texture);
9530 R_Mesh_TexMatrix(0, &layer->texmatrix);
9531 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9532 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9536 R_Mesh_TexBind(0, 0);
9537 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9539 // generate a color array for the fog pass
9540 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9541 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9545 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9548 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9550 GL_DepthFunc(GL_LEQUAL);
9551 GL_AlphaTest(false);
9555 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9559 r_vertexgeneric_t *batchvertex;
9562 // R_Mesh_ResetTextureState();
9563 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9565 if(rsurface.texture && rsurface.texture->currentskinframe)
9567 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9568 c[3] *= rsurface.texture->currentalpha;
9578 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9580 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9581 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9582 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9585 // brighten it up (as texture value 127 means "unlit")
9586 c[0] *= 2 * r_refdef.view.colorscale;
9587 c[1] *= 2 * r_refdef.view.colorscale;
9588 c[2] *= 2 * r_refdef.view.colorscale;
9590 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9591 c[3] *= r_wateralpha.value;
9593 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9595 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9596 GL_DepthMask(false);
9598 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9600 GL_BlendFunc(GL_ONE, GL_ONE);
9601 GL_DepthMask(false);
9603 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9605 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9606 GL_DepthMask(false);
9608 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9610 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9611 GL_DepthMask(false);
9615 GL_BlendFunc(GL_ONE, GL_ZERO);
9616 GL_DepthMask(writedepth);
9619 if (r_showsurfaces.integer == 3)
9621 rsurface.passcolor4f = NULL;
9623 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9625 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9627 rsurface.passcolor4f = NULL;
9628 rsurface.passcolor4f_vertexbuffer = 0;
9629 rsurface.passcolor4f_bufferoffset = 0;
9631 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9633 qboolean applycolor = true;
9636 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9638 r_refdef.lightmapintensity = 1;
9639 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9640 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9642 else if (FAKELIGHT_ENABLED)
9644 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9646 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9647 RSurf_DrawBatch_GL11_ApplyFakeLight();
9648 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9652 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9654 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9655 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9656 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9659 if(!rsurface.passcolor4f)
9660 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9662 RSurf_DrawBatch_GL11_ApplyAmbient();
9663 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9664 if(r_refdef.fogenabled)
9665 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9666 RSurf_DrawBatch_GL11_ClampColor();
9668 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9669 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9672 else if (!r_refdef.view.showdebug)
9674 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9675 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9676 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9678 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9679 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9681 R_Mesh_PrepareVertices_Generic_Unlock();
9684 else if (r_showsurfaces.integer == 4)
9686 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9687 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9688 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9690 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9691 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9692 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9694 R_Mesh_PrepareVertices_Generic_Unlock();
9697 else if (r_showsurfaces.integer == 2)
9700 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9701 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9702 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9704 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9705 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9706 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9707 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9708 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9709 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9710 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9712 R_Mesh_PrepareVertices_Generic_Unlock();
9713 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9717 int texturesurfaceindex;
9719 const msurface_t *surface;
9720 float surfacecolor4f[4];
9721 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9722 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9724 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9726 surface = texturesurfacelist[texturesurfaceindex];
9727 k = (int)(((size_t)surface) / sizeof(msurface_t));
9728 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9729 for (j = 0;j < surface->num_vertices;j++)
9731 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9732 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9736 R_Mesh_PrepareVertices_Generic_Unlock();
9741 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9744 RSurf_SetupDepthAndCulling();
9745 if (r_showsurfaces.integer)
9747 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9750 switch (vid.renderpath)
9752 case RENDERPATH_GL20:
9753 case RENDERPATH_D3D9:
9754 case RENDERPATH_D3D10:
9755 case RENDERPATH_D3D11:
9756 case RENDERPATH_SOFT:
9757 case RENDERPATH_GLES2:
9758 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9760 case RENDERPATH_GL13:
9761 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9763 case RENDERPATH_GL11:
9764 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9770 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9773 RSurf_SetupDepthAndCulling();
9774 if (r_showsurfaces.integer)
9776 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9779 switch (vid.renderpath)
9781 case RENDERPATH_GL20:
9782 case RENDERPATH_D3D9:
9783 case RENDERPATH_D3D10:
9784 case RENDERPATH_D3D11:
9785 case RENDERPATH_SOFT:
9786 case RENDERPATH_GLES2:
9787 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9789 case RENDERPATH_GL13:
9790 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9792 case RENDERPATH_GL11:
9793 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9799 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9802 int texturenumsurfaces, endsurface;
9804 const msurface_t *surface;
9805 #define MAXBATCH_TRANSPARENTSURFACES 256
9806 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9808 // if the model is static it doesn't matter what value we give for
9809 // wantnormals and wanttangents, so this logic uses only rules applicable
9810 // to a model, knowing that they are meaningless otherwise
9811 if (ent == r_refdef.scene.worldentity)
9812 RSurf_ActiveWorldEntity();
9813 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9814 RSurf_ActiveModelEntity(ent, false, false, false);
9817 switch (vid.renderpath)
9819 case RENDERPATH_GL20:
9820 case RENDERPATH_D3D9:
9821 case RENDERPATH_D3D10:
9822 case RENDERPATH_D3D11:
9823 case RENDERPATH_SOFT:
9824 case RENDERPATH_GLES2:
9825 RSurf_ActiveModelEntity(ent, true, true, false);
9827 case RENDERPATH_GL13:
9828 case RENDERPATH_GL11:
9829 RSurf_ActiveModelEntity(ent, true, false, false);
9834 if (r_transparentdepthmasking.integer)
9836 qboolean setup = false;
9837 for (i = 0;i < numsurfaces;i = j)
9840 surface = rsurface.modelsurfaces + surfacelist[i];
9841 texture = surface->texture;
9842 rsurface.texture = R_GetCurrentTexture(texture);
9843 rsurface.lightmaptexture = NULL;
9844 rsurface.deluxemaptexture = NULL;
9845 rsurface.uselightmaptexture = false;
9846 // scan ahead until we find a different texture
9847 endsurface = min(i + 1024, numsurfaces);
9848 texturenumsurfaces = 0;
9849 texturesurfacelist[texturenumsurfaces++] = surface;
9850 for (;j < endsurface;j++)
9852 surface = rsurface.modelsurfaces + surfacelist[j];
9853 if (texture != surface->texture)
9855 texturesurfacelist[texturenumsurfaces++] = surface;
9857 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9859 // render the range of surfaces as depth
9863 GL_ColorMask(0,0,0,0);
9866 GL_BlendFunc(GL_ONE, GL_ZERO);
9868 // R_Mesh_ResetTextureState();
9869 R_SetupShader_DepthOrShadow();
9871 RSurf_SetupDepthAndCulling();
9872 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9873 if (rsurface.batchvertex3fbuffer)
9874 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9876 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9880 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9883 for (i = 0;i < numsurfaces;i = j)
9886 surface = rsurface.modelsurfaces + surfacelist[i];
9887 texture = surface->texture;
9888 rsurface.texture = R_GetCurrentTexture(texture);
9889 // scan ahead until we find a different texture
9890 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9891 texturenumsurfaces = 0;
9892 texturesurfacelist[texturenumsurfaces++] = surface;
9893 if(FAKELIGHT_ENABLED)
9895 rsurface.lightmaptexture = NULL;
9896 rsurface.deluxemaptexture = NULL;
9897 rsurface.uselightmaptexture = false;
9898 for (;j < endsurface;j++)
9900 surface = rsurface.modelsurfaces + surfacelist[j];
9901 if (texture != surface->texture)
9903 texturesurfacelist[texturenumsurfaces++] = surface;
9908 rsurface.lightmaptexture = surface->lightmaptexture;
9909 rsurface.deluxemaptexture = surface->deluxemaptexture;
9910 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9911 for (;j < endsurface;j++)
9913 surface = rsurface.modelsurfaces + surfacelist[j];
9914 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9916 texturesurfacelist[texturenumsurfaces++] = surface;
9919 // render the range of surfaces
9920 if (ent == r_refdef.scene.worldentity)
9921 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9923 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9925 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9928 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9930 // transparent surfaces get pushed off into the transparent queue
9931 int surfacelistindex;
9932 const msurface_t *surface;
9933 vec3_t tempcenter, center;
9934 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9936 surface = texturesurfacelist[surfacelistindex];
9937 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9938 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9939 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9940 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9941 if (queueentity->transparent_offset) // transparent offset
9943 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9944 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9945 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9947 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9951 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9953 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9955 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9957 RSurf_SetupDepthAndCulling();
9958 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9959 if (rsurface.batchvertex3fbuffer)
9960 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9962 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9966 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9968 const entity_render_t *queueentity = r_refdef.scene.worldentity;
9971 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9974 if (!rsurface.texture->currentnumlayers)
9976 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9977 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9979 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9981 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9982 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9983 else if (!rsurface.texture->currentnumlayers)
9985 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9987 // in the deferred case, transparent surfaces were queued during prepass
9988 if (!r_shadow_usingdeferredprepass)
9989 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9993 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9994 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9999 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10002 texture_t *texture;
10003 R_FrameData_SetMark();
10004 // break the surface list down into batches by texture and use of lightmapping
10005 for (i = 0;i < numsurfaces;i = j)
10008 // texture is the base texture pointer, rsurface.texture is the
10009 // current frame/skin the texture is directing us to use (for example
10010 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10011 // use skin 1 instead)
10012 texture = surfacelist[i]->texture;
10013 rsurface.texture = R_GetCurrentTexture(texture);
10014 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10016 // if this texture is not the kind we want, skip ahead to the next one
10017 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10021 if(FAKELIGHT_ENABLED || depthonly || prepass)
10023 rsurface.lightmaptexture = NULL;
10024 rsurface.deluxemaptexture = NULL;
10025 rsurface.uselightmaptexture = false;
10026 // simply scan ahead until we find a different texture or lightmap state
10027 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10032 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10033 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10034 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10035 // simply scan ahead until we find a different texture or lightmap state
10036 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10039 // render the range of surfaces
10040 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10042 R_FrameData_ReturnToMark();
10045 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10049 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10052 if (!rsurface.texture->currentnumlayers)
10054 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10055 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10057 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10059 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10060 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10061 else if (!rsurface.texture->currentnumlayers)
10063 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10065 // in the deferred case, transparent surfaces were queued during prepass
10066 if (!r_shadow_usingdeferredprepass)
10067 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10071 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10072 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10077 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10080 texture_t *texture;
10081 R_FrameData_SetMark();
10082 // break the surface list down into batches by texture and use of lightmapping
10083 for (i = 0;i < numsurfaces;i = j)
10086 // texture is the base texture pointer, rsurface.texture is the
10087 // current frame/skin the texture is directing us to use (for example
10088 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10089 // use skin 1 instead)
10090 texture = surfacelist[i]->texture;
10091 rsurface.texture = R_GetCurrentTexture(texture);
10092 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10094 // if this texture is not the kind we want, skip ahead to the next one
10095 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10099 if(FAKELIGHT_ENABLED || depthonly || prepass)
10101 rsurface.lightmaptexture = NULL;
10102 rsurface.deluxemaptexture = NULL;
10103 rsurface.uselightmaptexture = false;
10104 // simply scan ahead until we find a different texture or lightmap state
10105 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10110 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10111 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10112 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10113 // simply scan ahead until we find a different texture or lightmap state
10114 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10117 // render the range of surfaces
10118 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10120 R_FrameData_ReturnToMark();
10123 float locboxvertex3f[6*4*3] =
10125 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10126 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10127 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10128 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10129 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10130 1,0,0, 0,0,0, 0,1,0, 1,1,0
10133 unsigned short locboxelements[6*2*3] =
10138 12,13,14, 12,14,15,
10139 16,17,18, 16,18,19,
10143 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10146 cl_locnode_t *loc = (cl_locnode_t *)ent;
10148 float vertex3f[6*4*3];
10150 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10151 GL_DepthMask(false);
10152 GL_DepthRange(0, 1);
10153 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10154 GL_DepthTest(true);
10155 GL_CullFace(GL_NONE);
10156 R_EntityMatrix(&identitymatrix);
10158 // R_Mesh_ResetTextureState();
10160 i = surfacelist[0];
10161 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10162 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10163 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10164 surfacelist[0] < 0 ? 0.5f : 0.125f);
10166 if (VectorCompare(loc->mins, loc->maxs))
10168 VectorSet(size, 2, 2, 2);
10169 VectorMA(loc->mins, -0.5f, size, mins);
10173 VectorCopy(loc->mins, mins);
10174 VectorSubtract(loc->maxs, loc->mins, size);
10177 for (i = 0;i < 6*4*3;)
10178 for (j = 0;j < 3;j++, i++)
10179 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10181 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10182 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10183 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10186 void R_DrawLocs(void)
10189 cl_locnode_t *loc, *nearestloc;
10191 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10192 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10194 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10195 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10199 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10201 if (decalsystem->decals)
10202 Mem_Free(decalsystem->decals);
10203 memset(decalsystem, 0, sizeof(*decalsystem));
10206 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)
10209 tridecal_t *decals;
10212 // expand or initialize the system
10213 if (decalsystem->maxdecals <= decalsystem->numdecals)
10215 decalsystem_t old = *decalsystem;
10216 qboolean useshortelements;
10217 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10218 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10219 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)));
10220 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10221 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10222 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10223 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10224 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10225 if (decalsystem->numdecals)
10226 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10228 Mem_Free(old.decals);
10229 for (i = 0;i < decalsystem->maxdecals*3;i++)
10230 decalsystem->element3i[i] = i;
10231 if (useshortelements)
10232 for (i = 0;i < decalsystem->maxdecals*3;i++)
10233 decalsystem->element3s[i] = i;
10236 // grab a decal and search for another free slot for the next one
10237 decals = decalsystem->decals;
10238 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10239 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10241 decalsystem->freedecal = i;
10242 if (decalsystem->numdecals <= i)
10243 decalsystem->numdecals = i + 1;
10245 // initialize the decal
10247 decal->triangleindex = triangleindex;
10248 decal->surfaceindex = surfaceindex;
10249 decal->decalsequence = decalsequence;
10250 decal->color4f[0][0] = c0[0];
10251 decal->color4f[0][1] = c0[1];
10252 decal->color4f[0][2] = c0[2];
10253 decal->color4f[0][3] = 1;
10254 decal->color4f[1][0] = c1[0];
10255 decal->color4f[1][1] = c1[1];
10256 decal->color4f[1][2] = c1[2];
10257 decal->color4f[1][3] = 1;
10258 decal->color4f[2][0] = c2[0];
10259 decal->color4f[2][1] = c2[1];
10260 decal->color4f[2][2] = c2[2];
10261 decal->color4f[2][3] = 1;
10262 decal->vertex3f[0][0] = v0[0];
10263 decal->vertex3f[0][1] = v0[1];
10264 decal->vertex3f[0][2] = v0[2];
10265 decal->vertex3f[1][0] = v1[0];
10266 decal->vertex3f[1][1] = v1[1];
10267 decal->vertex3f[1][2] = v1[2];
10268 decal->vertex3f[2][0] = v2[0];
10269 decal->vertex3f[2][1] = v2[1];
10270 decal->vertex3f[2][2] = v2[2];
10271 decal->texcoord2f[0][0] = t0[0];
10272 decal->texcoord2f[0][1] = t0[1];
10273 decal->texcoord2f[1][0] = t1[0];
10274 decal->texcoord2f[1][1] = t1[1];
10275 decal->texcoord2f[2][0] = t2[0];
10276 decal->texcoord2f[2][1] = t2[1];
10279 extern cvar_t cl_decals_bias;
10280 extern cvar_t cl_decals_models;
10281 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10282 // baseparms, parms, temps
10283 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)
10288 const float *vertex3f;
10289 const float *normal3f;
10291 float points[2][9][3];
10298 e = rsurface.modelelement3i + 3*triangleindex;
10300 vertex3f = rsurface.modelvertex3f;
10301 normal3f = rsurface.modelnormal3f;
10303 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10305 index = 3*e[cornerindex];
10306 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10309 //TriangleNormal(v[0], v[1], v[2], normal);
10310 //if (DotProduct(normal, localnormal) < 0.0f)
10312 // clip by each of the box planes formed from the projection matrix
10313 // if anything survives, we emit the decal
10314 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]);
10317 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]);
10320 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]);
10323 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]);
10326 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]);
10329 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]);
10332 // some part of the triangle survived, so we have to accept it...
10335 // dynamic always uses the original triangle
10337 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10339 index = 3*e[cornerindex];
10340 VectorCopy(vertex3f + index, v[cornerindex]);
10343 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10345 // convert vertex positions to texcoords
10346 Matrix4x4_Transform(projection, v[cornerindex], temp);
10347 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10348 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10349 // calculate distance fade from the projection origin
10350 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10351 f = bound(0.0f, f, 1.0f);
10352 c[cornerindex][0] = r * f;
10353 c[cornerindex][1] = g * f;
10354 c[cornerindex][2] = b * f;
10355 c[cornerindex][3] = 1.0f;
10356 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10359 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);
10361 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10362 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);
10364 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)
10366 matrix4x4_t projection;
10367 decalsystem_t *decalsystem;
10370 const msurface_t *surface;
10371 const msurface_t *surfaces;
10372 const int *surfacelist;
10373 const texture_t *texture;
10375 int numsurfacelist;
10376 int surfacelistindex;
10379 float localorigin[3];
10380 float localnormal[3];
10381 float localmins[3];
10382 float localmaxs[3];
10385 float planes[6][4];
10388 int bih_triangles_count;
10389 int bih_triangles[256];
10390 int bih_surfaces[256];
10392 decalsystem = &ent->decalsystem;
10393 model = ent->model;
10394 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10396 R_DecalSystem_Reset(&ent->decalsystem);
10400 if (!model->brush.data_leafs && !cl_decals_models.integer)
10402 if (decalsystem->model)
10403 R_DecalSystem_Reset(decalsystem);
10407 if (decalsystem->model != model)
10408 R_DecalSystem_Reset(decalsystem);
10409 decalsystem->model = model;
10411 RSurf_ActiveModelEntity(ent, true, false, false);
10413 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10414 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10415 VectorNormalize(localnormal);
10416 localsize = worldsize*rsurface.inversematrixscale;
10417 localmins[0] = localorigin[0] - localsize;
10418 localmins[1] = localorigin[1] - localsize;
10419 localmins[2] = localorigin[2] - localsize;
10420 localmaxs[0] = localorigin[0] + localsize;
10421 localmaxs[1] = localorigin[1] + localsize;
10422 localmaxs[2] = localorigin[2] + localsize;
10424 //VectorCopy(localnormal, planes[4]);
10425 //VectorVectors(planes[4], planes[2], planes[0]);
10426 AnglesFromVectors(angles, localnormal, NULL, false);
10427 AngleVectors(angles, planes[0], planes[2], planes[4]);
10428 VectorNegate(planes[0], planes[1]);
10429 VectorNegate(planes[2], planes[3]);
10430 VectorNegate(planes[4], planes[5]);
10431 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10432 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10433 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10434 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10435 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10436 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10441 matrix4x4_t forwardprojection;
10442 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10443 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10448 float projectionvector[4][3];
10449 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10450 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10451 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10452 projectionvector[0][0] = planes[0][0] * ilocalsize;
10453 projectionvector[0][1] = planes[1][0] * ilocalsize;
10454 projectionvector[0][2] = planes[2][0] * ilocalsize;
10455 projectionvector[1][0] = planes[0][1] * ilocalsize;
10456 projectionvector[1][1] = planes[1][1] * ilocalsize;
10457 projectionvector[1][2] = planes[2][1] * ilocalsize;
10458 projectionvector[2][0] = planes[0][2] * ilocalsize;
10459 projectionvector[2][1] = planes[1][2] * ilocalsize;
10460 projectionvector[2][2] = planes[2][2] * ilocalsize;
10461 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10462 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10463 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10464 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10468 dynamic = model->surfmesh.isanimated;
10469 numsurfacelist = model->nummodelsurfaces;
10470 surfacelist = model->sortedmodelsurfaces;
10471 surfaces = model->data_surfaces;
10474 bih_triangles_count = -1;
10477 if(model->render_bih.numleafs)
10478 bih = &model->render_bih;
10479 else if(model->collision_bih.numleafs)
10480 bih = &model->collision_bih;
10483 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10484 if(bih_triangles_count == 0)
10486 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10488 if(bih_triangles_count > 0)
10490 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10492 surfaceindex = bih_surfaces[triangleindex];
10493 surface = surfaces + surfaceindex;
10494 texture = surface->texture;
10495 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10497 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10499 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10504 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10506 surfaceindex = surfacelist[surfacelistindex];
10507 surface = surfaces + surfaceindex;
10508 // check cull box first because it rejects more than any other check
10509 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10511 // skip transparent surfaces
10512 texture = surface->texture;
10513 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10515 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10517 numtriangles = surface->num_triangles;
10518 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10519 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10524 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10525 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)
10527 int renderentityindex;
10528 float worldmins[3];
10529 float worldmaxs[3];
10530 entity_render_t *ent;
10532 if (!cl_decals_newsystem.integer)
10535 worldmins[0] = worldorigin[0] - worldsize;
10536 worldmins[1] = worldorigin[1] - worldsize;
10537 worldmins[2] = worldorigin[2] - worldsize;
10538 worldmaxs[0] = worldorigin[0] + worldsize;
10539 worldmaxs[1] = worldorigin[1] + worldsize;
10540 worldmaxs[2] = worldorigin[2] + worldsize;
10542 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10544 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10546 ent = r_refdef.scene.entities[renderentityindex];
10547 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10550 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10554 typedef struct r_decalsystem_splatqueue_s
10556 vec3_t worldorigin;
10557 vec3_t worldnormal;
10563 r_decalsystem_splatqueue_t;
10565 int r_decalsystem_numqueued = 0;
10566 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10568 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)
10570 r_decalsystem_splatqueue_t *queue;
10572 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10575 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10576 VectorCopy(worldorigin, queue->worldorigin);
10577 VectorCopy(worldnormal, queue->worldnormal);
10578 Vector4Set(queue->color, r, g, b, a);
10579 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10580 queue->worldsize = worldsize;
10581 queue->decalsequence = cl.decalsequence++;
10584 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10587 r_decalsystem_splatqueue_t *queue;
10589 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10590 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);
10591 r_decalsystem_numqueued = 0;
10594 extern cvar_t cl_decals_max;
10595 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10598 decalsystem_t *decalsystem = &ent->decalsystem;
10605 if (!decalsystem->numdecals)
10608 if (r_showsurfaces.integer)
10611 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10613 R_DecalSystem_Reset(decalsystem);
10617 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10618 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10620 if (decalsystem->lastupdatetime)
10621 frametime = (cl.time - decalsystem->lastupdatetime);
10624 decalsystem->lastupdatetime = cl.time;
10625 decal = decalsystem->decals;
10626 numdecals = decalsystem->numdecals;
10628 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10630 if (decal->color4f[0][3])
10632 decal->lived += frametime;
10633 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10635 memset(decal, 0, sizeof(*decal));
10636 if (decalsystem->freedecal > i)
10637 decalsystem->freedecal = i;
10641 decal = decalsystem->decals;
10642 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10645 // collapse the array by shuffling the tail decals into the gaps
10648 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10649 decalsystem->freedecal++;
10650 if (decalsystem->freedecal == numdecals)
10652 decal[decalsystem->freedecal] = decal[--numdecals];
10655 decalsystem->numdecals = numdecals;
10657 if (numdecals <= 0)
10659 // if there are no decals left, reset decalsystem
10660 R_DecalSystem_Reset(decalsystem);
10664 extern skinframe_t *decalskinframe;
10665 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10668 decalsystem_t *decalsystem = &ent->decalsystem;
10677 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10680 numdecals = decalsystem->numdecals;
10684 if (r_showsurfaces.integer)
10687 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10689 R_DecalSystem_Reset(decalsystem);
10693 // if the model is static it doesn't matter what value we give for
10694 // wantnormals and wanttangents, so this logic uses only rules applicable
10695 // to a model, knowing that they are meaningless otherwise
10696 if (ent == r_refdef.scene.worldentity)
10697 RSurf_ActiveWorldEntity();
10699 RSurf_ActiveModelEntity(ent, false, false, false);
10701 decalsystem->lastupdatetime = cl.time;
10702 decal = decalsystem->decals;
10704 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10706 // update vertex positions for animated models
10707 v3f = decalsystem->vertex3f;
10708 c4f = decalsystem->color4f;
10709 t2f = decalsystem->texcoord2f;
10710 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10712 if (!decal->color4f[0][3])
10715 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10718 // update color values for fading decals
10719 if (decal->lived >= cl_decals_time.value)
10720 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10724 c4f[ 0] = decal->color4f[0][0] * alpha;
10725 c4f[ 1] = decal->color4f[0][1] * alpha;
10726 c4f[ 2] = decal->color4f[0][2] * alpha;
10728 c4f[ 4] = decal->color4f[1][0] * alpha;
10729 c4f[ 5] = decal->color4f[1][1] * alpha;
10730 c4f[ 6] = decal->color4f[1][2] * alpha;
10732 c4f[ 8] = decal->color4f[2][0] * alpha;
10733 c4f[ 9] = decal->color4f[2][1] * alpha;
10734 c4f[10] = decal->color4f[2][2] * alpha;
10737 t2f[0] = decal->texcoord2f[0][0];
10738 t2f[1] = decal->texcoord2f[0][1];
10739 t2f[2] = decal->texcoord2f[1][0];
10740 t2f[3] = decal->texcoord2f[1][1];
10741 t2f[4] = decal->texcoord2f[2][0];
10742 t2f[5] = decal->texcoord2f[2][1];
10744 // update vertex positions for animated models
10745 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10747 e = rsurface.modelelement3i + 3*decal->triangleindex;
10748 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10749 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10750 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10754 VectorCopy(decal->vertex3f[0], v3f);
10755 VectorCopy(decal->vertex3f[1], v3f + 3);
10756 VectorCopy(decal->vertex3f[2], v3f + 6);
10759 if (r_refdef.fogenabled)
10761 alpha = RSurf_FogVertex(v3f);
10762 VectorScale(c4f, alpha, c4f);
10763 alpha = RSurf_FogVertex(v3f + 3);
10764 VectorScale(c4f + 4, alpha, c4f + 4);
10765 alpha = RSurf_FogVertex(v3f + 6);
10766 VectorScale(c4f + 8, alpha, c4f + 8);
10777 r_refdef.stats.drawndecals += numtris;
10779 // now render the decals all at once
10780 // (this assumes they all use one particle font texture!)
10781 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);
10782 // R_Mesh_ResetTextureState();
10783 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10784 GL_DepthMask(false);
10785 GL_DepthRange(0, 1);
10786 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10787 GL_DepthTest(true);
10788 GL_CullFace(GL_NONE);
10789 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10790 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10791 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10795 static void R_DrawModelDecals(void)
10799 // fade faster when there are too many decals
10800 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10801 for (i = 0;i < r_refdef.scene.numentities;i++)
10802 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10804 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10805 for (i = 0;i < r_refdef.scene.numentities;i++)
10806 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10807 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10809 R_DecalSystem_ApplySplatEntitiesQueue();
10811 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10812 for (i = 0;i < r_refdef.scene.numentities;i++)
10813 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10815 r_refdef.stats.totaldecals += numdecals;
10817 if (r_showsurfaces.integer)
10820 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10822 for (i = 0;i < r_refdef.scene.numentities;i++)
10824 if (!r_refdef.viewcache.entityvisible[i])
10826 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10827 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10831 extern cvar_t mod_collision_bih;
10832 void R_DrawDebugModel(void)
10834 entity_render_t *ent = rsurface.entity;
10835 int i, j, k, l, flagsmask;
10836 const msurface_t *surface;
10837 dp_model_t *model = ent->model;
10840 switch(vid.renderpath)
10842 case RENDERPATH_GL11:
10843 case RENDERPATH_GL13:
10844 case RENDERPATH_GL20:
10846 case RENDERPATH_D3D9:
10847 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10849 case RENDERPATH_D3D10:
10850 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10852 case RENDERPATH_D3D11:
10853 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10855 case RENDERPATH_SOFT:
10856 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10858 case RENDERPATH_GLES2:
10859 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10863 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10865 // R_Mesh_ResetTextureState();
10866 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10867 GL_DepthRange(0, 1);
10868 GL_DepthTest(!r_showdisabledepthtest.integer);
10869 GL_DepthMask(false);
10870 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10872 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10876 qboolean cullbox = ent == r_refdef.scene.worldentity;
10877 const q3mbrush_t *brush;
10878 const bih_t *bih = &model->collision_bih;
10879 const bih_leaf_t *bihleaf;
10880 float vertex3f[3][3];
10881 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10883 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10885 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10887 switch (bihleaf->type)
10890 brush = model->brush.data_brushes + bihleaf->itemindex;
10891 if (brush->colbrushf && brush->colbrushf->numtriangles)
10893 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);
10894 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10895 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10898 case BIH_COLLISIONTRIANGLE:
10899 triangleindex = bihleaf->itemindex;
10900 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10901 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10902 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10903 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);
10904 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10905 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10907 case BIH_RENDERTRIANGLE:
10908 triangleindex = bihleaf->itemindex;
10909 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10910 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10911 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10912 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);
10913 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10914 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10920 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10922 if (r_showtris.integer || (r_shownormals.value != 0))
10924 if (r_showdisabledepthtest.integer)
10926 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10927 GL_DepthMask(false);
10931 GL_BlendFunc(GL_ONE, GL_ZERO);
10932 GL_DepthMask(true);
10934 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10936 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10938 rsurface.texture = R_GetCurrentTexture(surface->texture);
10939 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10941 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10942 if (r_showtris.value > 0)
10944 if (!rsurface.texture->currentlayers->depthmask)
10945 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10946 else if (ent == r_refdef.scene.worldentity)
10947 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10949 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10950 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10951 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10953 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10956 if (r_shownormals.value < 0)
10958 qglBegin(GL_LINES);
10959 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10961 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10962 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10963 qglVertex3f(v[0], v[1], v[2]);
10964 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10965 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10966 qglVertex3f(v[0], v[1], v[2]);
10971 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10973 qglBegin(GL_LINES);
10974 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10976 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10977 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10978 qglVertex3f(v[0], v[1], v[2]);
10979 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10980 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10981 qglVertex3f(v[0], v[1], v[2]);
10985 qglBegin(GL_LINES);
10986 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10988 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10989 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10990 qglVertex3f(v[0], v[1], v[2]);
10991 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10992 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10993 qglVertex3f(v[0], v[1], v[2]);
10997 qglBegin(GL_LINES);
10998 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11000 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11001 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11002 qglVertex3f(v[0], v[1], v[2]);
11003 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11004 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11005 qglVertex3f(v[0], v[1], v[2]);
11012 rsurface.texture = NULL;
11016 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11017 int r_maxsurfacelist = 0;
11018 const msurface_t **r_surfacelist = NULL;
11019 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11021 int i, j, endj, flagsmask;
11022 dp_model_t *model = r_refdef.scene.worldmodel;
11023 msurface_t *surfaces;
11024 unsigned char *update;
11025 int numsurfacelist = 0;
11029 if (r_maxsurfacelist < model->num_surfaces)
11031 r_maxsurfacelist = model->num_surfaces;
11033 Mem_Free((msurface_t**)r_surfacelist);
11034 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11037 RSurf_ActiveWorldEntity();
11039 surfaces = model->data_surfaces;
11040 update = model->brushq1.lightmapupdateflags;
11042 // update light styles on this submodel
11043 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11045 model_brush_lightstyleinfo_t *style;
11046 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11048 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11050 int *list = style->surfacelist;
11051 style->value = r_refdef.scene.lightstylevalue[style->style];
11052 for (j = 0;j < style->numsurfaces;j++)
11053 update[list[j]] = true;
11058 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11062 R_DrawDebugModel();
11063 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11067 rsurface.lightmaptexture = NULL;
11068 rsurface.deluxemaptexture = NULL;
11069 rsurface.uselightmaptexture = false;
11070 rsurface.texture = NULL;
11071 rsurface.rtlight = NULL;
11072 numsurfacelist = 0;
11073 // add visible surfaces to draw list
11074 for (i = 0;i < model->nummodelsurfaces;i++)
11076 j = model->sortedmodelsurfaces[i];
11077 if (r_refdef.viewcache.world_surfacevisible[j])
11078 r_surfacelist[numsurfacelist++] = surfaces + j;
11080 // update lightmaps if needed
11081 if (model->brushq1.firstrender)
11083 model->brushq1.firstrender = false;
11084 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11086 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11090 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11091 if (r_refdef.viewcache.world_surfacevisible[j])
11093 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11095 // don't do anything if there were no surfaces
11096 if (!numsurfacelist)
11098 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11101 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11103 // add to stats if desired
11104 if (r_speeds.integer && !skysurfaces && !depthonly)
11106 r_refdef.stats.world_surfaces += numsurfacelist;
11107 for (j = 0;j < numsurfacelist;j++)
11108 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11111 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11114 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11116 int i, j, endj, flagsmask;
11117 dp_model_t *model = ent->model;
11118 msurface_t *surfaces;
11119 unsigned char *update;
11120 int numsurfacelist = 0;
11124 if (r_maxsurfacelist < model->num_surfaces)
11126 r_maxsurfacelist = model->num_surfaces;
11128 Mem_Free((msurface_t **)r_surfacelist);
11129 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11132 // if the model is static it doesn't matter what value we give for
11133 // wantnormals and wanttangents, so this logic uses only rules applicable
11134 // to a model, knowing that they are meaningless otherwise
11135 if (ent == r_refdef.scene.worldentity)
11136 RSurf_ActiveWorldEntity();
11137 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11138 RSurf_ActiveModelEntity(ent, false, false, false);
11140 RSurf_ActiveModelEntity(ent, true, true, true);
11141 else if (depthonly)
11143 switch (vid.renderpath)
11145 case RENDERPATH_GL20:
11146 case RENDERPATH_D3D9:
11147 case RENDERPATH_D3D10:
11148 case RENDERPATH_D3D11:
11149 case RENDERPATH_SOFT:
11150 case RENDERPATH_GLES2:
11151 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11153 case RENDERPATH_GL13:
11154 case RENDERPATH_GL11:
11155 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11161 switch (vid.renderpath)
11163 case RENDERPATH_GL20:
11164 case RENDERPATH_D3D9:
11165 case RENDERPATH_D3D10:
11166 case RENDERPATH_D3D11:
11167 case RENDERPATH_SOFT:
11168 case RENDERPATH_GLES2:
11169 RSurf_ActiveModelEntity(ent, true, true, false);
11171 case RENDERPATH_GL13:
11172 case RENDERPATH_GL11:
11173 RSurf_ActiveModelEntity(ent, true, false, false);
11178 surfaces = model->data_surfaces;
11179 update = model->brushq1.lightmapupdateflags;
11181 // update light styles
11182 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11184 model_brush_lightstyleinfo_t *style;
11185 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11187 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11189 int *list = style->surfacelist;
11190 style->value = r_refdef.scene.lightstylevalue[style->style];
11191 for (j = 0;j < style->numsurfaces;j++)
11192 update[list[j]] = true;
11197 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11201 R_DrawDebugModel();
11202 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11206 rsurface.lightmaptexture = NULL;
11207 rsurface.deluxemaptexture = NULL;
11208 rsurface.uselightmaptexture = false;
11209 rsurface.texture = NULL;
11210 rsurface.rtlight = NULL;
11211 numsurfacelist = 0;
11212 // add visible surfaces to draw list
11213 for (i = 0;i < model->nummodelsurfaces;i++)
11214 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11215 // don't do anything if there were no surfaces
11216 if (!numsurfacelist)
11218 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11221 // update lightmaps if needed
11225 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11230 R_BuildLightMap(ent, surfaces + j);
11235 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11237 R_BuildLightMap(ent, surfaces + j);
11238 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11240 // add to stats if desired
11241 if (r_speeds.integer && !skysurfaces && !depthonly)
11243 r_refdef.stats.entities_surfaces += numsurfacelist;
11244 for (j = 0;j < numsurfacelist;j++)
11245 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11248 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11251 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11253 static texture_t texture;
11254 static msurface_t surface;
11255 const msurface_t *surfacelist = &surface;
11257 // fake enough texture and surface state to render this geometry
11259 texture.update_lastrenderframe = -1; // regenerate this texture
11260 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11261 texture.currentskinframe = skinframe;
11262 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11263 texture.offsetmapping = OFFSETMAPPING_OFF;
11264 texture.offsetscale = 1;
11265 texture.specularscalemod = 1;
11266 texture.specularpowermod = 1;
11268 surface.texture = &texture;
11269 surface.num_triangles = numtriangles;
11270 surface.num_firsttriangle = firsttriangle;
11271 surface.num_vertices = numvertices;
11272 surface.num_firstvertex = firstvertex;
11275 rsurface.texture = R_GetCurrentTexture(surface.texture);
11276 rsurface.lightmaptexture = NULL;
11277 rsurface.deluxemaptexture = NULL;
11278 rsurface.uselightmaptexture = false;
11279 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11282 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)
11284 static msurface_t surface;
11285 const msurface_t *surfacelist = &surface;
11287 // fake enough texture and surface state to render this geometry
11288 surface.texture = texture;
11289 surface.num_triangles = numtriangles;
11290 surface.num_firsttriangle = firsttriangle;
11291 surface.num_vertices = numvertices;
11292 surface.num_firstvertex = firstvertex;
11295 rsurface.texture = R_GetCurrentTexture(surface.texture);
11296 rsurface.lightmaptexture = NULL;
11297 rsurface.deluxemaptexture = NULL;
11298 rsurface.uselightmaptexture = false;
11299 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);