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;
1991 #define BLENDFUNC_ALLOWS_COLORMOD 1
1992 #define BLENDFUNC_ALLOWS_FOG 2
1993 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
1994 #define BLENDFUNC_ALLOWS_ANYFOG 6
1995 static int R_BlendFuncFlags(int src, int dst)
1999 // a blendfunc allows colormod if:
2000 // a) it can never keep the destination pixel invariant, or
2001 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2002 // this is to prevent unintended side effects from colormod
2004 // a blendfunc allows fog if:
2005 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2006 // this is to prevent unintended side effects from fog
2008 // these checks are the output of fogeval.pl
2010 r |= BLENDFUNC_ALLOWS_COLORMOD;
2011 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2012 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2013 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2014 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2015 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2016 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2017 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2018 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2019 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2020 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2021 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2022 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2023 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2024 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2025 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2026 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2027 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2028 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2029 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2030 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2035 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)
2037 // select a permutation of the lighting shader appropriate to this
2038 // combination of texture, entity, light source, and fogging, only use the
2039 // minimum features necessary to avoid wasting rendering time in the
2040 // fragment shader on features that are not being used
2041 unsigned int permutation = 0;
2042 unsigned int mode = 0;
2044 static float dummy_colormod[3] = {1, 1, 1};
2045 float *colormod = rsurface.colormod;
2047 matrix4x4_t tempmatrix;
2048 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2049 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2050 permutation |= SHADERPERMUTATION_ALPHAKILL;
2051 if (rsurfacepass == RSURFPASS_BACKGROUND)
2053 // distorted background
2054 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2056 mode = SHADERMODE_WATER;
2057 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2058 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2059 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2061 // this is the right thing to do for wateralpha
2062 GL_BlendFunc(GL_ONE, GL_ZERO);
2063 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2067 // this is the right thing to do for entity alpha
2068 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2069 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2072 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2074 mode = SHADERMODE_REFRACTION;
2075 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2076 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2080 mode = SHADERMODE_GENERIC;
2081 permutation |= SHADERPERMUTATION_DIFFUSE;
2082 GL_BlendFunc(GL_ONE, GL_ZERO);
2083 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2086 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2088 if (r_glsl_offsetmapping.integer)
2090 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2091 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2092 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2093 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2094 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2096 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2097 if (r_glsl_offsetmapping_reliefmapping.integer)
2098 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2101 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2102 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2103 // normalmap (deferred prepass), may use alpha test on diffuse
2104 mode = SHADERMODE_DEFERREDGEOMETRY;
2105 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2106 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2107 GL_BlendFunc(GL_ONE, GL_ZERO);
2108 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2110 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2112 if (r_glsl_offsetmapping.integer)
2114 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2115 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2116 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2117 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2118 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2120 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2121 if (r_glsl_offsetmapping_reliefmapping.integer)
2122 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2125 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2126 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2128 mode = SHADERMODE_LIGHTSOURCE;
2129 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2130 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2131 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2132 permutation |= SHADERPERMUTATION_CUBEFILTER;
2133 if (diffusescale > 0)
2134 permutation |= SHADERPERMUTATION_DIFFUSE;
2135 if (specularscale > 0)
2136 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2137 if (r_refdef.fogenabled)
2138 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2139 if (rsurface.texture->colormapping)
2140 permutation |= SHADERPERMUTATION_COLORMAPPING;
2141 if (r_shadow_usingshadowmap2d)
2143 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2144 if(r_shadow_shadowmapvsdct)
2145 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2147 if (r_shadow_shadowmapsampler)
2148 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2149 if (r_shadow_shadowmappcf > 1)
2150 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2151 else if (r_shadow_shadowmappcf)
2152 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2154 if (rsurface.texture->reflectmasktexture)
2155 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2156 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2157 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2159 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2161 if (r_glsl_offsetmapping.integer)
2163 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2164 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2165 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2166 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2167 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2169 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2170 if (r_glsl_offsetmapping_reliefmapping.integer)
2171 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2174 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2175 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2176 // unshaded geometry (fullbright or ambient model lighting)
2177 mode = SHADERMODE_FLATCOLOR;
2178 ambientscale = diffusescale = specularscale = 0;
2179 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2180 permutation |= SHADERPERMUTATION_GLOW;
2181 if (r_refdef.fogenabled)
2182 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2183 if (rsurface.texture->colormapping)
2184 permutation |= SHADERPERMUTATION_COLORMAPPING;
2185 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2187 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2188 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2190 if (r_shadow_shadowmapsampler)
2191 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2192 if (r_shadow_shadowmappcf > 1)
2193 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2194 else if (r_shadow_shadowmappcf)
2195 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2197 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2198 permutation |= SHADERPERMUTATION_REFLECTION;
2199 if (rsurface.texture->reflectmasktexture)
2200 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2201 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2202 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2204 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2206 if (r_glsl_offsetmapping.integer)
2208 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2209 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2210 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2211 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2212 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2214 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2215 if (r_glsl_offsetmapping_reliefmapping.integer)
2216 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2219 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2220 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2221 // directional model lighting
2222 mode = SHADERMODE_LIGHTDIRECTION;
2223 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2224 permutation |= SHADERPERMUTATION_GLOW;
2225 permutation |= SHADERPERMUTATION_DIFFUSE;
2226 if (specularscale > 0)
2227 permutation |= SHADERPERMUTATION_SPECULAR;
2228 if (r_refdef.fogenabled)
2229 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2230 if (rsurface.texture->colormapping)
2231 permutation |= SHADERPERMUTATION_COLORMAPPING;
2232 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2234 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2235 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2237 if (r_shadow_shadowmapsampler)
2238 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2239 if (r_shadow_shadowmappcf > 1)
2240 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2241 else if (r_shadow_shadowmappcf)
2242 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2244 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2245 permutation |= SHADERPERMUTATION_REFLECTION;
2246 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2247 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2248 if (rsurface.texture->reflectmasktexture)
2249 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2250 if (r_shadow_bouncegridtexture)
2251 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2252 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2253 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2255 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2257 if (r_glsl_offsetmapping.integer)
2259 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2260 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2261 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2262 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2263 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2265 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2266 if (r_glsl_offsetmapping_reliefmapping.integer)
2267 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2270 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2271 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2272 // ambient model lighting
2273 mode = SHADERMODE_LIGHTDIRECTION;
2274 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2275 permutation |= SHADERPERMUTATION_GLOW;
2276 if (r_refdef.fogenabled)
2277 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2278 if (rsurface.texture->colormapping)
2279 permutation |= SHADERPERMUTATION_COLORMAPPING;
2280 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2282 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2283 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2285 if (r_shadow_shadowmapsampler)
2286 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2287 if (r_shadow_shadowmappcf > 1)
2288 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2289 else if (r_shadow_shadowmappcf)
2290 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2292 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2293 permutation |= SHADERPERMUTATION_REFLECTION;
2294 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2295 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2296 if (rsurface.texture->reflectmasktexture)
2297 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2298 if (r_shadow_bouncegridtexture)
2299 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2300 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2301 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2305 if (r_glsl_offsetmapping.integer)
2307 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2308 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2309 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2310 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2311 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2313 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2314 if (r_glsl_offsetmapping_reliefmapping.integer)
2315 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2318 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2319 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2321 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2322 permutation |= SHADERPERMUTATION_GLOW;
2323 if (r_refdef.fogenabled)
2324 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2325 if (rsurface.texture->colormapping)
2326 permutation |= SHADERPERMUTATION_COLORMAPPING;
2327 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2329 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2330 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2332 if (r_shadow_shadowmapsampler)
2333 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2334 if (r_shadow_shadowmappcf > 1)
2335 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2336 else if (r_shadow_shadowmappcf)
2337 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2339 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2340 permutation |= SHADERPERMUTATION_REFLECTION;
2341 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2342 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2343 if (rsurface.texture->reflectmasktexture)
2344 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2345 if (FAKELIGHT_ENABLED)
2347 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2348 mode = SHADERMODE_FAKELIGHT;
2349 permutation |= SHADERPERMUTATION_DIFFUSE;
2350 if (specularscale > 0)
2351 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2353 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2355 // deluxemapping (light direction texture)
2356 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2357 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2359 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2360 permutation |= SHADERPERMUTATION_DIFFUSE;
2361 if (specularscale > 0)
2362 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2364 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2366 // fake deluxemapping (uniform light direction in tangentspace)
2367 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2368 permutation |= SHADERPERMUTATION_DIFFUSE;
2369 if (specularscale > 0)
2370 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2372 else if (rsurface.uselightmaptexture)
2374 // ordinary lightmapping (q1bsp, q3bsp)
2375 mode = SHADERMODE_LIGHTMAP;
2379 // ordinary vertex coloring (q3bsp)
2380 mode = SHADERMODE_VERTEXCOLOR;
2382 if (r_shadow_bouncegridtexture)
2383 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2384 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2385 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2387 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2388 colormod = dummy_colormod;
2389 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2390 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2391 switch(vid.renderpath)
2393 case RENDERPATH_D3D9:
2395 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);
2396 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2397 R_SetupShader_SetPermutationHLSL(mode, permutation);
2398 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2399 if (mode == SHADERMODE_LIGHTSOURCE)
2401 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2402 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2406 if (mode == SHADERMODE_LIGHTDIRECTION)
2408 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2411 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2412 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2413 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2414 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2415 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2417 if (mode == SHADERMODE_LIGHTSOURCE)
2419 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2420 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2421 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2422 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2423 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2425 // additive passes are only darkened by fog, not tinted
2426 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2427 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2431 if (mode == SHADERMODE_FLATCOLOR)
2433 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2435 else if (mode == SHADERMODE_LIGHTDIRECTION)
2437 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]);
2438 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2439 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);
2440 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);
2441 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2442 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2443 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2447 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2448 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2449 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);
2450 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);
2451 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2453 // additive passes are only darkened by fog, not tinted
2454 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2455 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2457 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2458 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);
2459 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2460 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2461 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2462 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2463 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2464 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2465 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2466 if (mode == SHADERMODE_WATER)
2467 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2469 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2470 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2471 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2472 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));
2473 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2474 if (rsurface.texture->pantstexture)
2475 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2477 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2478 if (rsurface.texture->shirttexture)
2479 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2481 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2482 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2483 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2484 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2485 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2486 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2487 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2488 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2490 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2491 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2492 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2493 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2494 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2495 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2496 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2497 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2498 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2499 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2500 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2501 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2502 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2503 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2504 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2505 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2506 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2507 if (rsurfacepass == RSURFPASS_BACKGROUND)
2509 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2510 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2511 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2515 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2517 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2518 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2519 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2520 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2521 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2523 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2524 if (rsurface.rtlight)
2526 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2527 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2532 case RENDERPATH_D3D10:
2533 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2535 case RENDERPATH_D3D11:
2536 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2538 case RENDERPATH_GL20:
2539 case RENDERPATH_GLES2:
2540 if (!vid.useinterleavedarrays)
2542 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);
2543 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2544 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2545 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2546 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2547 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2548 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2549 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2553 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);
2554 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2556 R_SetupShader_SetPermutationGLSL(mode, permutation);
2557 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2558 if (mode == SHADERMODE_LIGHTSOURCE)
2560 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2561 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2562 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2563 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2564 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2565 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);
2567 // additive passes are only darkened by fog, not tinted
2568 if (r_glsl_permutation->loc_FogColor >= 0)
2569 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2570 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2574 if (mode == SHADERMODE_FLATCOLOR)
2576 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2578 else if (mode == SHADERMODE_LIGHTDIRECTION)
2580 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]);
2581 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]);
2582 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);
2583 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);
2584 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);
2585 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]);
2586 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]);
2590 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]);
2591 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]);
2592 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);
2593 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);
2594 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);
2596 // additive passes are only darkened by fog, not tinted
2597 if (r_glsl_permutation->loc_FogColor >= 0)
2599 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2600 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2602 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2604 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);
2605 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]);
2606 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]);
2607 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]);
2608 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]);
2609 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2610 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2611 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2612 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]);
2614 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2615 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2616 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2617 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]);
2618 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]);
2620 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2621 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));
2622 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2623 if (r_glsl_permutation->loc_Color_Pants >= 0)
2625 if (rsurface.texture->pantstexture)
2626 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2628 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2630 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2632 if (rsurface.texture->shirttexture)
2633 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2635 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2637 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]);
2638 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2639 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2640 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2641 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2642 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]);
2643 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2644 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);}
2645 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2647 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2648 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2649 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2650 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2651 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2652 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2653 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2654 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2655 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2656 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2657 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2658 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2659 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2660 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2661 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);
2662 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2663 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2664 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2665 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2666 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2667 if (rsurfacepass == RSURFPASS_BACKGROUND)
2669 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);
2670 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);
2671 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);
2675 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);
2677 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2678 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2679 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2680 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2681 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2683 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2684 if (rsurface.rtlight)
2686 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2687 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2690 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2693 case RENDERPATH_GL13:
2694 case RENDERPATH_GL11:
2696 case RENDERPATH_SOFT:
2697 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);
2698 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2699 R_SetupShader_SetPermutationSoft(mode, permutation);
2700 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2701 if (mode == SHADERMODE_LIGHTSOURCE)
2703 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2704 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2705 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2706 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2707 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2708 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2710 // additive passes are only darkened by fog, not tinted
2711 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2712 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2716 if (mode == SHADERMODE_FLATCOLOR)
2718 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2720 else if (mode == SHADERMODE_LIGHTDIRECTION)
2722 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]);
2723 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2724 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);
2725 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);
2726 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2727 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]);
2728 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2732 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2733 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2734 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);
2735 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);
2736 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2738 // additive passes are only darkened by fog, not tinted
2739 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2740 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2742 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2743 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);
2744 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2745 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2746 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]);
2747 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]);
2748 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2749 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2750 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2751 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2753 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2754 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2755 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2756 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2757 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]);
2759 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2760 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));
2761 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2762 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2764 if (rsurface.texture->pantstexture)
2765 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2767 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2769 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2771 if (rsurface.texture->shirttexture)
2772 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2776 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2777 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2778 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2779 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2780 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2781 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2782 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2784 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2785 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2786 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2787 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2788 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2789 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2790 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2791 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2792 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2793 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2794 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2795 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2796 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2797 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2798 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2799 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2800 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2801 if (rsurfacepass == RSURFPASS_BACKGROUND)
2803 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2804 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2805 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2809 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2811 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2812 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2813 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2814 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2815 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2817 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2818 if (rsurface.rtlight)
2820 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2821 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2828 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2830 // select a permutation of the lighting shader appropriate to this
2831 // combination of texture, entity, light source, and fogging, only use the
2832 // minimum features necessary to avoid wasting rendering time in the
2833 // fragment shader on features that are not being used
2834 unsigned int permutation = 0;
2835 unsigned int mode = 0;
2836 const float *lightcolorbase = rtlight->currentcolor;
2837 float ambientscale = rtlight->ambientscale;
2838 float diffusescale = rtlight->diffusescale;
2839 float specularscale = rtlight->specularscale;
2840 // this is the location of the light in view space
2841 vec3_t viewlightorigin;
2842 // this transforms from view space (camera) to light space (cubemap)
2843 matrix4x4_t viewtolight;
2844 matrix4x4_t lighttoview;
2845 float viewtolight16f[16];
2846 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2848 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2849 if (rtlight->currentcubemap != r_texture_whitecube)
2850 permutation |= SHADERPERMUTATION_CUBEFILTER;
2851 if (diffusescale > 0)
2852 permutation |= SHADERPERMUTATION_DIFFUSE;
2853 if (specularscale > 0)
2854 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2855 if (r_shadow_usingshadowmap2d)
2857 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2858 if (r_shadow_shadowmapvsdct)
2859 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2861 if (r_shadow_shadowmapsampler)
2862 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2863 if (r_shadow_shadowmappcf > 1)
2864 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2865 else if (r_shadow_shadowmappcf)
2866 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2868 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2869 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2870 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2871 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2872 switch(vid.renderpath)
2874 case RENDERPATH_D3D9:
2876 R_SetupShader_SetPermutationHLSL(mode, permutation);
2877 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2878 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2879 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2880 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2881 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2882 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2883 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2884 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2885 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2886 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2888 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2889 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2890 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2891 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2892 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2893 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2896 case RENDERPATH_D3D10:
2897 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2899 case RENDERPATH_D3D11:
2900 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2902 case RENDERPATH_GL20:
2903 case RENDERPATH_GLES2:
2904 R_SetupShader_SetPermutationGLSL(mode, permutation);
2905 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2906 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2907 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);
2908 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);
2909 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);
2910 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]);
2911 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]);
2912 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));
2913 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]);
2914 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2916 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2917 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2918 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2919 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2920 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2921 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2923 case RENDERPATH_GL13:
2924 case RENDERPATH_GL11:
2926 case RENDERPATH_SOFT:
2927 R_SetupShader_SetPermutationGLSL(mode, permutation);
2928 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2929 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2930 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2931 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2932 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2933 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2934 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]);
2935 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));
2936 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2937 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2939 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2940 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2941 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2942 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2943 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2944 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2949 #define SKINFRAME_HASH 1024
2953 int loadsequence; // incremented each level change
2954 memexpandablearray_t array;
2955 skinframe_t *hash[SKINFRAME_HASH];
2958 r_skinframe_t r_skinframe;
2960 void R_SkinFrame_PrepareForPurge(void)
2962 r_skinframe.loadsequence++;
2963 // wrap it without hitting zero
2964 if (r_skinframe.loadsequence >= 200)
2965 r_skinframe.loadsequence = 1;
2968 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2972 // mark the skinframe as used for the purging code
2973 skinframe->loadsequence = r_skinframe.loadsequence;
2976 void R_SkinFrame_Purge(void)
2980 for (i = 0;i < SKINFRAME_HASH;i++)
2982 for (s = r_skinframe.hash[i];s;s = s->next)
2984 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2986 if (s->merged == s->base)
2988 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2989 R_PurgeTexture(s->stain );s->stain = NULL;
2990 R_PurgeTexture(s->merged);s->merged = NULL;
2991 R_PurgeTexture(s->base );s->base = NULL;
2992 R_PurgeTexture(s->pants );s->pants = NULL;
2993 R_PurgeTexture(s->shirt );s->shirt = NULL;
2994 R_PurgeTexture(s->nmap );s->nmap = NULL;
2995 R_PurgeTexture(s->gloss );s->gloss = NULL;
2996 R_PurgeTexture(s->glow );s->glow = NULL;
2997 R_PurgeTexture(s->fog );s->fog = NULL;
2998 R_PurgeTexture(s->reflect);s->reflect = NULL;
2999 s->loadsequence = 0;
3005 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3007 char basename[MAX_QPATH];
3009 Image_StripImageExtension(name, basename, sizeof(basename));
3011 if( last == NULL ) {
3013 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3014 item = r_skinframe.hash[hashindex];
3019 // linearly search through the hash bucket
3020 for( ; item ; item = item->next ) {
3021 if( !strcmp( item->basename, basename ) ) {
3028 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3032 char basename[MAX_QPATH];
3034 Image_StripImageExtension(name, basename, sizeof(basename));
3036 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3037 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3038 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3042 rtexture_t *dyntexture;
3043 // check whether its a dynamic texture
3044 dyntexture = CL_GetDynTexture( basename );
3045 if (!add && !dyntexture)
3047 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3048 memset(item, 0, sizeof(*item));
3049 strlcpy(item->basename, basename, sizeof(item->basename));
3050 item->base = dyntexture; // either NULL or dyntexture handle
3051 item->textureflags = textureflags;
3052 item->comparewidth = comparewidth;
3053 item->compareheight = compareheight;
3054 item->comparecrc = comparecrc;
3055 item->next = r_skinframe.hash[hashindex];
3056 r_skinframe.hash[hashindex] = item;
3058 else if( item->base == NULL )
3060 rtexture_t *dyntexture;
3061 // check whether its a dynamic texture
3062 // 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]
3063 dyntexture = CL_GetDynTexture( basename );
3064 item->base = dyntexture; // either NULL or dyntexture handle
3067 R_SkinFrame_MarkUsed(item);
3071 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3073 unsigned long long avgcolor[5], wsum; \
3081 for(pix = 0; pix < cnt; ++pix) \
3084 for(comp = 0; comp < 3; ++comp) \
3086 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3089 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3091 for(comp = 0; comp < 3; ++comp) \
3092 avgcolor[comp] += getpixel * w; \
3095 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3096 avgcolor[4] += getpixel; \
3098 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3100 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3101 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3102 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3103 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3106 extern cvar_t gl_picmip;
3107 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3110 unsigned char *pixels;
3111 unsigned char *bumppixels;
3112 unsigned char *basepixels = NULL;
3113 int basepixels_width = 0;
3114 int basepixels_height = 0;
3115 skinframe_t *skinframe;
3116 rtexture_t *ddsbase = NULL;
3117 qboolean ddshasalpha = false;
3118 float ddsavgcolor[4];
3119 char basename[MAX_QPATH];
3120 int miplevel = R_PicmipForFlags(textureflags);
3121 int savemiplevel = miplevel;
3124 if (cls.state == ca_dedicated)
3127 // return an existing skinframe if already loaded
3128 // if loading of the first image fails, don't make a new skinframe as it
3129 // would cause all future lookups of this to be missing
3130 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3131 if (skinframe && skinframe->base)
3134 Image_StripImageExtension(name, basename, sizeof(basename));
3136 // check for DDS texture file first
3137 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3139 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3140 if (basepixels == NULL)
3144 // FIXME handle miplevel
3146 if (developer_loading.integer)
3147 Con_Printf("loading skin \"%s\"\n", name);
3149 // we've got some pixels to store, so really allocate this new texture now
3151 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3152 skinframe->stain = NULL;
3153 skinframe->merged = NULL;
3154 skinframe->base = NULL;
3155 skinframe->pants = NULL;
3156 skinframe->shirt = NULL;
3157 skinframe->nmap = NULL;
3158 skinframe->gloss = NULL;
3159 skinframe->glow = NULL;
3160 skinframe->fog = NULL;
3161 skinframe->reflect = NULL;
3162 skinframe->hasalpha = false;
3166 skinframe->base = ddsbase;
3167 skinframe->hasalpha = ddshasalpha;
3168 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3169 if (r_loadfog && skinframe->hasalpha)
3170 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3171 //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]);
3175 basepixels_width = image_width;
3176 basepixels_height = image_height;
3177 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);
3178 if (textureflags & TEXF_ALPHA)
3180 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3182 if (basepixels[j] < 255)
3184 skinframe->hasalpha = true;
3188 if (r_loadfog && skinframe->hasalpha)
3190 // has transparent pixels
3191 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3192 for (j = 0;j < image_width * image_height * 4;j += 4)
3197 pixels[j+3] = basepixels[j+3];
3199 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);
3203 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3204 //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]);
3205 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3206 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3207 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3208 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3213 mymiplevel = savemiplevel;
3214 if (r_loadnormalmap)
3215 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);
3216 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3218 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3219 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3220 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3221 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3224 // _norm is the name used by tenebrae and has been adopted as standard
3225 if (r_loadnormalmap && skinframe->nmap == NULL)
3227 mymiplevel = savemiplevel;
3228 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3230 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);
3234 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3236 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3237 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3238 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);
3240 Mem_Free(bumppixels);
3242 else if (r_shadow_bumpscale_basetexture.value > 0)
3244 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3245 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3246 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);
3249 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3250 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3253 // _luma is supported only for tenebrae compatibility
3254 // _glow is the preferred name
3255 mymiplevel = savemiplevel;
3256 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))))
3258 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);
3259 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3260 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3261 Mem_Free(pixels);pixels = NULL;
3264 mymiplevel = savemiplevel;
3265 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3267 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);
3268 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3269 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3274 mymiplevel = savemiplevel;
3275 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3277 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);
3278 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3279 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3284 mymiplevel = savemiplevel;
3285 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3287 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);
3288 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3289 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3294 mymiplevel = savemiplevel;
3295 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3297 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);
3298 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3299 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3305 Mem_Free(basepixels);
3310 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3311 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3314 unsigned char *temp1, *temp2;
3315 skinframe_t *skinframe;
3317 if (cls.state == ca_dedicated)
3320 // if already loaded just return it, otherwise make a new skinframe
3321 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3322 if (skinframe && skinframe->base)
3325 skinframe->stain = NULL;
3326 skinframe->merged = NULL;
3327 skinframe->base = NULL;
3328 skinframe->pants = NULL;
3329 skinframe->shirt = NULL;
3330 skinframe->nmap = NULL;
3331 skinframe->gloss = NULL;
3332 skinframe->glow = NULL;
3333 skinframe->fog = NULL;
3334 skinframe->reflect = NULL;
3335 skinframe->hasalpha = false;
3337 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3341 if (developer_loading.integer)
3342 Con_Printf("loading 32bit skin \"%s\"\n", name);
3344 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3346 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3347 temp2 = temp1 + width * height * 4;
3348 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3349 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);
3352 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3353 if (textureflags & TEXF_ALPHA)
3355 for (i = 3;i < width * height * 4;i += 4)
3357 if (skindata[i] < 255)
3359 skinframe->hasalpha = true;
3363 if (r_loadfog && skinframe->hasalpha)
3365 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3366 memcpy(fogpixels, skindata, width * height * 4);
3367 for (i = 0;i < width * height * 4;i += 4)
3368 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3369 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3370 Mem_Free(fogpixels);
3374 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3375 //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]);
3380 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3384 skinframe_t *skinframe;
3386 if (cls.state == ca_dedicated)
3389 // if already loaded just return it, otherwise make a new skinframe
3390 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3391 if (skinframe && skinframe->base)
3394 skinframe->stain = NULL;
3395 skinframe->merged = NULL;
3396 skinframe->base = NULL;
3397 skinframe->pants = NULL;
3398 skinframe->shirt = NULL;
3399 skinframe->nmap = NULL;
3400 skinframe->gloss = NULL;
3401 skinframe->glow = NULL;
3402 skinframe->fog = NULL;
3403 skinframe->reflect = NULL;
3404 skinframe->hasalpha = false;
3406 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3410 if (developer_loading.integer)
3411 Con_Printf("loading quake skin \"%s\"\n", name);
3413 // 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)
3414 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3415 memcpy(skinframe->qpixels, skindata, width*height);
3416 skinframe->qwidth = width;
3417 skinframe->qheight = height;
3420 for (i = 0;i < width * height;i++)
3421 featuresmask |= palette_featureflags[skindata[i]];
3423 skinframe->hasalpha = false;
3424 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3425 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3426 skinframe->qgeneratemerged = true;
3427 skinframe->qgeneratebase = skinframe->qhascolormapping;
3428 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3430 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3431 //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]);
3436 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3440 unsigned char *skindata;
3442 if (!skinframe->qpixels)
3445 if (!skinframe->qhascolormapping)
3446 colormapped = false;
3450 if (!skinframe->qgeneratebase)
3455 if (!skinframe->qgeneratemerged)
3459 width = skinframe->qwidth;
3460 height = skinframe->qheight;
3461 skindata = skinframe->qpixels;
3463 if (skinframe->qgeneratenmap)
3465 unsigned char *temp1, *temp2;
3466 skinframe->qgeneratenmap = false;
3467 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3468 temp2 = temp1 + width * height * 4;
3469 // use either a custom palette or the quake palette
3470 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3471 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3472 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);
3476 if (skinframe->qgenerateglow)
3478 skinframe->qgenerateglow = false;
3479 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3484 skinframe->qgeneratebase = false;
3485 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);
3486 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3487 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3491 skinframe->qgeneratemerged = false;
3492 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);
3495 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3497 Mem_Free(skinframe->qpixels);
3498 skinframe->qpixels = NULL;
3502 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)
3505 skinframe_t *skinframe;
3507 if (cls.state == ca_dedicated)
3510 // if already loaded just return it, otherwise make a new skinframe
3511 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3512 if (skinframe && skinframe->base)
3515 skinframe->stain = NULL;
3516 skinframe->merged = NULL;
3517 skinframe->base = NULL;
3518 skinframe->pants = NULL;
3519 skinframe->shirt = NULL;
3520 skinframe->nmap = NULL;
3521 skinframe->gloss = NULL;
3522 skinframe->glow = NULL;
3523 skinframe->fog = NULL;
3524 skinframe->reflect = NULL;
3525 skinframe->hasalpha = false;
3527 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3531 if (developer_loading.integer)
3532 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3534 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3535 if (textureflags & TEXF_ALPHA)
3537 for (i = 0;i < width * height;i++)
3539 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3541 skinframe->hasalpha = true;
3545 if (r_loadfog && skinframe->hasalpha)
3546 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3549 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3550 //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]);
3555 skinframe_t *R_SkinFrame_LoadMissing(void)
3557 skinframe_t *skinframe;
3559 if (cls.state == ca_dedicated)
3562 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
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 skinframe->avgcolor[0] = rand() / RAND_MAX;
3576 skinframe->avgcolor[1] = rand() / RAND_MAX;
3577 skinframe->avgcolor[2] = rand() / RAND_MAX;
3578 skinframe->avgcolor[3] = 1;
3583 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3584 typedef struct suffixinfo_s
3587 qboolean flipx, flipy, flipdiagonal;
3590 static suffixinfo_t suffix[3][6] =
3593 {"px", false, false, false},
3594 {"nx", false, false, false},
3595 {"py", false, false, false},
3596 {"ny", false, false, false},
3597 {"pz", false, false, false},
3598 {"nz", false, false, false}
3601 {"posx", false, false, false},
3602 {"negx", false, false, false},
3603 {"posy", false, false, false},
3604 {"negy", false, false, false},
3605 {"posz", false, false, false},
3606 {"negz", false, false, false}
3609 {"rt", true, false, true},
3610 {"lf", false, true, true},
3611 {"ft", true, true, false},
3612 {"bk", false, false, false},
3613 {"up", true, false, true},
3614 {"dn", true, false, true}
3618 static int componentorder[4] = {0, 1, 2, 3};
3620 rtexture_t *R_LoadCubemap(const char *basename)
3622 int i, j, cubemapsize;
3623 unsigned char *cubemappixels, *image_buffer;
3624 rtexture_t *cubemaptexture;
3626 // must start 0 so the first loadimagepixels has no requested width/height
3628 cubemappixels = NULL;
3629 cubemaptexture = NULL;
3630 // keep trying different suffix groups (posx, px, rt) until one loads
3631 for (j = 0;j < 3 && !cubemappixels;j++)
3633 // load the 6 images in the suffix group
3634 for (i = 0;i < 6;i++)
3636 // generate an image name based on the base and and suffix
3637 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3639 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3641 // an image loaded, make sure width and height are equal
3642 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3644 // if this is the first image to load successfully, allocate the cubemap memory
3645 if (!cubemappixels && image_width >= 1)
3647 cubemapsize = image_width;
3648 // note this clears to black, so unavailable sides are black
3649 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3651 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3653 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);
3656 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3658 Mem_Free(image_buffer);
3662 // if a cubemap loaded, upload it
3665 if (developer_loading.integer)
3666 Con_Printf("loading cubemap \"%s\"\n", basename);
3668 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3669 Mem_Free(cubemappixels);
3673 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3674 if (developer_loading.integer)
3676 Con_Printf("(tried tried images ");
3677 for (j = 0;j < 3;j++)
3678 for (i = 0;i < 6;i++)
3679 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3680 Con_Print(" and was unable to find any of them).\n");
3683 return cubemaptexture;
3686 rtexture_t *R_GetCubemap(const char *basename)
3689 for (i = 0;i < r_texture_numcubemaps;i++)
3690 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3691 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3692 if (i >= MAX_CUBEMAPS)
3693 return r_texture_whitecube;
3694 r_texture_numcubemaps++;
3695 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3696 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3697 return r_texture_cubemaps[i].texture;
3700 void R_FreeCubemaps(void)
3703 for (i = 0;i < r_texture_numcubemaps;i++)
3705 if (developer_loading.integer)
3706 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3707 if (r_texture_cubemaps[i].texture)
3708 R_FreeTexture(r_texture_cubemaps[i].texture);
3710 r_texture_numcubemaps = 0;
3713 void R_Main_FreeViewCache(void)
3715 if (r_refdef.viewcache.entityvisible)
3716 Mem_Free(r_refdef.viewcache.entityvisible);
3717 if (r_refdef.viewcache.world_pvsbits)
3718 Mem_Free(r_refdef.viewcache.world_pvsbits);
3719 if (r_refdef.viewcache.world_leafvisible)
3720 Mem_Free(r_refdef.viewcache.world_leafvisible);
3721 if (r_refdef.viewcache.world_surfacevisible)
3722 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3723 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3726 void R_Main_ResizeViewCache(void)
3728 int numentities = r_refdef.scene.numentities;
3729 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3730 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3731 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3732 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3733 if (r_refdef.viewcache.maxentities < numentities)
3735 r_refdef.viewcache.maxentities = numentities;
3736 if (r_refdef.viewcache.entityvisible)
3737 Mem_Free(r_refdef.viewcache.entityvisible);
3738 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3740 if (r_refdef.viewcache.world_numclusters != numclusters)
3742 r_refdef.viewcache.world_numclusters = numclusters;
3743 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3744 if (r_refdef.viewcache.world_pvsbits)
3745 Mem_Free(r_refdef.viewcache.world_pvsbits);
3746 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3748 if (r_refdef.viewcache.world_numleafs != numleafs)
3750 r_refdef.viewcache.world_numleafs = numleafs;
3751 if (r_refdef.viewcache.world_leafvisible)
3752 Mem_Free(r_refdef.viewcache.world_leafvisible);
3753 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3755 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3757 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3758 if (r_refdef.viewcache.world_surfacevisible)
3759 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3760 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3764 extern rtexture_t *loadingscreentexture;
3765 void gl_main_start(void)
3767 loadingscreentexture = NULL;
3768 r_texture_blanknormalmap = NULL;
3769 r_texture_white = NULL;
3770 r_texture_grey128 = NULL;
3771 r_texture_black = NULL;
3772 r_texture_whitecube = NULL;
3773 r_texture_normalizationcube = NULL;
3774 r_texture_fogattenuation = NULL;
3775 r_texture_fogheighttexture = NULL;
3776 r_texture_gammaramps = NULL;
3777 r_texture_numcubemaps = 0;
3779 r_loaddds = r_texture_dds_load.integer != 0;
3780 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3782 switch(vid.renderpath)
3784 case RENDERPATH_GL20:
3785 case RENDERPATH_D3D9:
3786 case RENDERPATH_D3D10:
3787 case RENDERPATH_D3D11:
3788 case RENDERPATH_SOFT:
3789 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3790 Cvar_SetValueQuick(&gl_combine, 1);
3791 Cvar_SetValueQuick(&r_glsl, 1);
3792 r_loadnormalmap = true;
3796 case RENDERPATH_GL13:
3797 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3798 Cvar_SetValueQuick(&gl_combine, 1);
3799 Cvar_SetValueQuick(&r_glsl, 0);
3800 r_loadnormalmap = false;
3801 r_loadgloss = false;
3804 case RENDERPATH_GL11:
3805 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3806 Cvar_SetValueQuick(&gl_combine, 0);
3807 Cvar_SetValueQuick(&r_glsl, 0);
3808 r_loadnormalmap = false;
3809 r_loadgloss = false;
3812 case RENDERPATH_GLES2:
3813 Cvar_SetValueQuick(&r_textureunits, 1);
3814 Cvar_SetValueQuick(&gl_combine, 1);
3815 Cvar_SetValueQuick(&r_glsl, 1);
3816 r_loadnormalmap = true;
3817 r_loadgloss = false;
3823 R_FrameData_Reset();
3827 memset(r_queries, 0, sizeof(r_queries));
3829 r_qwskincache = NULL;
3830 r_qwskincache_size = 0;
3832 // set up r_skinframe loading system for textures
3833 memset(&r_skinframe, 0, sizeof(r_skinframe));
3834 r_skinframe.loadsequence = 1;
3835 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3837 r_main_texturepool = R_AllocTexturePool();
3838 R_BuildBlankTextures();
3840 if (vid.support.arb_texture_cube_map)
3843 R_BuildNormalizationCube();
3845 r_texture_fogattenuation = NULL;
3846 r_texture_fogheighttexture = NULL;
3847 r_texture_gammaramps = NULL;
3848 //r_texture_fogintensity = NULL;
3849 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3850 memset(&r_waterstate, 0, sizeof(r_waterstate));
3851 r_glsl_permutation = NULL;
3852 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3853 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3854 glslshaderstring = NULL;
3856 r_hlsl_permutation = NULL;
3857 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3858 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3860 hlslshaderstring = NULL;
3861 memset(&r_svbsp, 0, sizeof (r_svbsp));
3863 r_refdef.fogmasktable_density = 0;
3866 void gl_main_shutdown(void)
3869 R_FrameData_Reset();
3871 R_Main_FreeViewCache();
3873 switch(vid.renderpath)
3875 case RENDERPATH_GL11:
3876 case RENDERPATH_GL13:
3877 case RENDERPATH_GL20:
3878 case RENDERPATH_GLES2:
3880 qglDeleteQueriesARB(r_maxqueries, r_queries);
3882 case RENDERPATH_D3D9:
3883 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3885 case RENDERPATH_D3D10:
3886 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3888 case RENDERPATH_D3D11:
3889 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3891 case RENDERPATH_SOFT:
3897 memset(r_queries, 0, sizeof(r_queries));
3899 r_qwskincache = NULL;
3900 r_qwskincache_size = 0;
3902 // clear out the r_skinframe state
3903 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3904 memset(&r_skinframe, 0, sizeof(r_skinframe));
3907 Mem_Free(r_svbsp.nodes);
3908 memset(&r_svbsp, 0, sizeof (r_svbsp));
3909 R_FreeTexturePool(&r_main_texturepool);
3910 loadingscreentexture = NULL;
3911 r_texture_blanknormalmap = NULL;
3912 r_texture_white = NULL;
3913 r_texture_grey128 = NULL;
3914 r_texture_black = NULL;
3915 r_texture_whitecube = NULL;
3916 r_texture_normalizationcube = NULL;
3917 r_texture_fogattenuation = NULL;
3918 r_texture_fogheighttexture = NULL;
3919 r_texture_gammaramps = NULL;
3920 r_texture_numcubemaps = 0;
3921 //r_texture_fogintensity = NULL;
3922 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3923 memset(&r_waterstate, 0, sizeof(r_waterstate));
3926 r_glsl_permutation = NULL;
3927 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3928 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3929 glslshaderstring = NULL;
3931 r_hlsl_permutation = NULL;
3932 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3933 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3935 hlslshaderstring = NULL;
3938 extern void CL_ParseEntityLump(char *entitystring);
3939 void gl_main_newmap(void)
3941 // FIXME: move this code to client
3942 char *entities, entname[MAX_QPATH];
3944 Mem_Free(r_qwskincache);
3945 r_qwskincache = NULL;
3946 r_qwskincache_size = 0;
3949 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3950 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3952 CL_ParseEntityLump(entities);
3956 if (cl.worldmodel->brush.entities)
3957 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3959 R_Main_FreeViewCache();
3961 R_FrameData_Reset();
3964 void GL_Main_Init(void)
3966 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3968 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3969 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3970 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3971 if (gamemode == GAME_NEHAHRA)
3973 Cvar_RegisterVariable (&gl_fogenable);
3974 Cvar_RegisterVariable (&gl_fogdensity);
3975 Cvar_RegisterVariable (&gl_fogred);
3976 Cvar_RegisterVariable (&gl_foggreen);
3977 Cvar_RegisterVariable (&gl_fogblue);
3978 Cvar_RegisterVariable (&gl_fogstart);
3979 Cvar_RegisterVariable (&gl_fogend);
3980 Cvar_RegisterVariable (&gl_skyclip);
3982 Cvar_RegisterVariable(&r_motionblur);
3983 Cvar_RegisterVariable(&r_motionblur_maxblur);
3984 Cvar_RegisterVariable(&r_motionblur_bmin);
3985 Cvar_RegisterVariable(&r_motionblur_vmin);
3986 Cvar_RegisterVariable(&r_motionblur_vmax);
3987 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3988 Cvar_RegisterVariable(&r_motionblur_randomize);
3989 Cvar_RegisterVariable(&r_damageblur);
3990 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3991 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3992 Cvar_RegisterVariable(&r_equalize_entities_by);
3993 Cvar_RegisterVariable(&r_equalize_entities_to);
3994 Cvar_RegisterVariable(&r_depthfirst);
3995 Cvar_RegisterVariable(&r_useinfinitefarclip);
3996 Cvar_RegisterVariable(&r_farclip_base);
3997 Cvar_RegisterVariable(&r_farclip_world);
3998 Cvar_RegisterVariable(&r_nearclip);
3999 Cvar_RegisterVariable(&r_showbboxes);
4000 Cvar_RegisterVariable(&r_showsurfaces);
4001 Cvar_RegisterVariable(&r_showtris);
4002 Cvar_RegisterVariable(&r_shownormals);
4003 Cvar_RegisterVariable(&r_showlighting);
4004 Cvar_RegisterVariable(&r_showshadowvolumes);
4005 Cvar_RegisterVariable(&r_showcollisionbrushes);
4006 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4007 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4008 Cvar_RegisterVariable(&r_showdisabledepthtest);
4009 Cvar_RegisterVariable(&r_drawportals);
4010 Cvar_RegisterVariable(&r_drawentities);
4011 Cvar_RegisterVariable(&r_draw2d);
4012 Cvar_RegisterVariable(&r_drawworld);
4013 Cvar_RegisterVariable(&r_cullentities_trace);
4014 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4015 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4016 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4017 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4018 Cvar_RegisterVariable(&r_drawviewmodel);
4019 Cvar_RegisterVariable(&r_drawexteriormodel);
4020 Cvar_RegisterVariable(&r_speeds);
4021 Cvar_RegisterVariable(&r_fullbrights);
4022 Cvar_RegisterVariable(&r_wateralpha);
4023 Cvar_RegisterVariable(&r_dynamic);
4024 Cvar_RegisterVariable(&r_fakelight);
4025 Cvar_RegisterVariable(&r_fakelight_intensity);
4026 Cvar_RegisterVariable(&r_fullbright);
4027 Cvar_RegisterVariable(&r_shadows);
4028 Cvar_RegisterVariable(&r_shadows_darken);
4029 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4030 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4031 Cvar_RegisterVariable(&r_shadows_throwdistance);
4032 Cvar_RegisterVariable(&r_shadows_throwdirection);
4033 Cvar_RegisterVariable(&r_shadows_focus);
4034 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4035 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4036 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4037 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4038 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4039 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4040 Cvar_RegisterVariable(&r_fog_exp2);
4041 Cvar_RegisterVariable(&r_drawfog);
4042 Cvar_RegisterVariable(&r_transparentdepthmasking);
4043 Cvar_RegisterVariable(&r_texture_dds_load);
4044 Cvar_RegisterVariable(&r_texture_dds_save);
4045 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4046 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4047 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4048 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4049 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4050 Cvar_RegisterVariable(&r_textureunits);
4051 Cvar_RegisterVariable(&gl_combine);
4052 Cvar_RegisterVariable(&r_glsl);
4053 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4054 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4055 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4056 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4057 Cvar_RegisterVariable(&r_glsl_postprocess);
4058 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4059 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4060 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4061 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4062 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4063 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4064 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4065 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4067 Cvar_RegisterVariable(&r_water);
4068 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4069 Cvar_RegisterVariable(&r_water_clippingplanebias);
4070 Cvar_RegisterVariable(&r_water_refractdistort);
4071 Cvar_RegisterVariable(&r_water_reflectdistort);
4072 Cvar_RegisterVariable(&r_water_scissormode);
4073 Cvar_RegisterVariable(&r_lerpsprites);
4074 Cvar_RegisterVariable(&r_lerpmodels);
4075 Cvar_RegisterVariable(&r_lerplightstyles);
4076 Cvar_RegisterVariable(&r_waterscroll);
4077 Cvar_RegisterVariable(&r_bloom);
4078 Cvar_RegisterVariable(&r_bloom_colorscale);
4079 Cvar_RegisterVariable(&r_bloom_brighten);
4080 Cvar_RegisterVariable(&r_bloom_blur);
4081 Cvar_RegisterVariable(&r_bloom_resolution);
4082 Cvar_RegisterVariable(&r_bloom_colorexponent);
4083 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4084 Cvar_RegisterVariable(&r_hdr);
4085 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4086 Cvar_RegisterVariable(&r_hdr_glowintensity);
4087 Cvar_RegisterVariable(&r_hdr_range);
4088 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4089 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4090 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4091 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4092 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4093 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4094 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4095 Cvar_RegisterVariable(&developer_texturelogging);
4096 Cvar_RegisterVariable(&gl_lightmaps);
4097 Cvar_RegisterVariable(&r_test);
4098 Cvar_RegisterVariable(&r_glsl_saturation);
4099 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4100 Cvar_RegisterVariable(&r_framedatasize);
4101 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4102 Cvar_SetValue("r_fullbrights", 0);
4103 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4105 Cvar_RegisterVariable(&r_track_sprites);
4106 Cvar_RegisterVariable(&r_track_sprites_flags);
4107 Cvar_RegisterVariable(&r_track_sprites_scalew);
4108 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4109 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4110 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4111 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4112 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4115 extern void R_Textures_Init(void);
4116 extern void GL_Draw_Init(void);
4117 extern void GL_Main_Init(void);
4118 extern void R_Shadow_Init(void);
4119 extern void R_Sky_Init(void);
4120 extern void GL_Surf_Init(void);
4121 extern void R_Particles_Init(void);
4122 extern void R_Explosion_Init(void);
4123 extern void gl_backend_init(void);
4124 extern void Sbar_Init(void);
4125 extern void R_LightningBeams_Init(void);
4126 extern void Mod_RenderInit(void);
4127 extern void Font_Init(void);
4129 void Render_Init(void)
4142 R_LightningBeams_Init();
4151 extern char *ENGINE_EXTENSIONS;
4154 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4155 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4156 gl_version = (const char *)qglGetString(GL_VERSION);
4157 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4161 if (!gl_platformextensions)
4162 gl_platformextensions = "";
4164 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4165 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4166 Con_Printf("GL_VERSION: %s\n", gl_version);
4167 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4168 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4170 VID_CheckExtensions();
4172 // LordHavoc: report supported extensions
4173 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4175 // clear to black (loading plaque will be seen over this)
4176 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4179 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4183 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4185 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4188 p = r_refdef.view.frustum + i;
4193 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4197 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4201 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4205 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4209 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4213 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4217 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4221 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4229 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4233 for (i = 0;i < numplanes;i++)
4240 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4244 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4248 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4252 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4256 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4260 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4264 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4268 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4276 //==================================================================================
4278 // LordHavoc: this stores temporary data used within the same frame
4280 typedef struct r_framedata_mem_s
4282 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4283 size_t size; // how much usable space
4284 size_t current; // how much space in use
4285 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4286 size_t wantedsize; // how much space was allocated
4287 unsigned char *data; // start of real data (16byte aligned)
4291 static r_framedata_mem_t *r_framedata_mem;
4293 void R_FrameData_Reset(void)
4295 while (r_framedata_mem)
4297 r_framedata_mem_t *next = r_framedata_mem->purge;
4298 Mem_Free(r_framedata_mem);
4299 r_framedata_mem = next;
4303 void R_FrameData_Resize(void)
4306 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4307 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4308 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4310 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4311 newmem->wantedsize = wantedsize;
4312 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4313 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4314 newmem->current = 0;
4316 newmem->purge = r_framedata_mem;
4317 r_framedata_mem = newmem;
4321 void R_FrameData_NewFrame(void)
4323 R_FrameData_Resize();
4324 if (!r_framedata_mem)
4326 // if we ran out of space on the last frame, free the old memory now
4327 while (r_framedata_mem->purge)
4329 // repeatedly remove the second item in the list, leaving only head
4330 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4331 Mem_Free(r_framedata_mem->purge);
4332 r_framedata_mem->purge = next;
4334 // reset the current mem pointer
4335 r_framedata_mem->current = 0;
4336 r_framedata_mem->mark = 0;
4339 void *R_FrameData_Alloc(size_t size)
4343 // align to 16 byte boundary - the data pointer is already aligned, so we
4344 // only need to ensure the size of every allocation is also aligned
4345 size = (size + 15) & ~15;
4347 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4349 // emergency - we ran out of space, allocate more memory
4350 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4351 R_FrameData_Resize();
4354 data = r_framedata_mem->data + r_framedata_mem->current;
4355 r_framedata_mem->current += size;
4357 // count the usage for stats
4358 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4359 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4361 return (void *)data;
4364 void *R_FrameData_Store(size_t size, void *data)
4366 void *d = R_FrameData_Alloc(size);
4368 memcpy(d, data, size);
4372 void R_FrameData_SetMark(void)
4374 if (!r_framedata_mem)
4376 r_framedata_mem->mark = r_framedata_mem->current;
4379 void R_FrameData_ReturnToMark(void)
4381 if (!r_framedata_mem)
4383 r_framedata_mem->current = r_framedata_mem->mark;
4386 //==================================================================================
4388 // LordHavoc: animcache originally written by Echon, rewritten since then
4391 * Animation cache prevents re-generating mesh data for an animated model
4392 * multiple times in one frame for lighting, shadowing, reflections, etc.
4395 void R_AnimCache_Free(void)
4399 void R_AnimCache_ClearCache(void)
4402 entity_render_t *ent;
4404 for (i = 0;i < r_refdef.scene.numentities;i++)
4406 ent = r_refdef.scene.entities[i];
4407 ent->animcache_vertex3f = NULL;
4408 ent->animcache_normal3f = NULL;
4409 ent->animcache_svector3f = NULL;
4410 ent->animcache_tvector3f = NULL;
4411 ent->animcache_vertexmesh = NULL;
4412 ent->animcache_vertex3fbuffer = NULL;
4413 ent->animcache_vertexmeshbuffer = NULL;
4417 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4421 // check if we need the meshbuffers
4422 if (!vid.useinterleavedarrays)
4425 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4426 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4427 // TODO: upload vertex3f buffer?
4428 if (ent->animcache_vertexmesh)
4430 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4431 for (i = 0;i < numvertices;i++)
4432 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4433 if (ent->animcache_svector3f)
4434 for (i = 0;i < numvertices;i++)
4435 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4436 if (ent->animcache_tvector3f)
4437 for (i = 0;i < numvertices;i++)
4438 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4439 if (ent->animcache_normal3f)
4440 for (i = 0;i < numvertices;i++)
4441 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4442 // TODO: upload vertexmeshbuffer?
4446 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4448 dp_model_t *model = ent->model;
4450 // see if it's already cached this frame
4451 if (ent->animcache_vertex3f)
4453 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4454 if (wantnormals || wanttangents)
4456 if (ent->animcache_normal3f)
4457 wantnormals = false;
4458 if (ent->animcache_svector3f)
4459 wanttangents = false;
4460 if (wantnormals || wanttangents)
4462 numvertices = model->surfmesh.num_vertices;
4464 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4467 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4468 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4470 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4471 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4477 // see if this ent is worth caching
4478 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4480 // get some memory for this entity and generate mesh data
4481 numvertices = model->surfmesh.num_vertices;
4482 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4484 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4487 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4488 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4490 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4491 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4496 void R_AnimCache_CacheVisibleEntities(void)
4499 qboolean wantnormals = true;
4500 qboolean wanttangents = !r_showsurfaces.integer;
4502 switch(vid.renderpath)
4504 case RENDERPATH_GL20:
4505 case RENDERPATH_D3D9:
4506 case RENDERPATH_D3D10:
4507 case RENDERPATH_D3D11:
4508 case RENDERPATH_GLES2:
4510 case RENDERPATH_GL13:
4511 case RENDERPATH_GL11:
4512 wanttangents = false;
4514 case RENDERPATH_SOFT:
4518 if (r_shownormals.integer)
4519 wanttangents = wantnormals = true;
4521 // TODO: thread this
4522 // NOTE: R_PrepareRTLights() also caches entities
4524 for (i = 0;i < r_refdef.scene.numentities;i++)
4525 if (r_refdef.viewcache.entityvisible[i])
4526 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4529 //==================================================================================
4531 static void R_View_UpdateEntityLighting (void)
4534 entity_render_t *ent;
4535 vec3_t tempdiffusenormal, avg;
4536 vec_t f, fa, fd, fdd;
4537 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4539 for (i = 0;i < r_refdef.scene.numentities;i++)
4541 ent = r_refdef.scene.entities[i];
4543 // skip unseen models
4544 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4548 if (ent->model && ent->model->brush.num_leafs)
4550 // TODO: use modellight for r_ambient settings on world?
4551 VectorSet(ent->modellight_ambient, 0, 0, 0);
4552 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4553 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4557 // fetch the lighting from the worldmodel data
4558 VectorClear(ent->modellight_ambient);
4559 VectorClear(ent->modellight_diffuse);
4560 VectorClear(tempdiffusenormal);
4561 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4564 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4566 // complete lightning for lit sprites
4567 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4568 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4570 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4571 org[2] = org[2] + r_overheadsprites_pushback.value;
4572 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4575 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4577 if(ent->flags & RENDER_EQUALIZE)
4579 // first fix up ambient lighting...
4580 if(r_equalize_entities_minambient.value > 0)
4582 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4585 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4586 if(fa < r_equalize_entities_minambient.value * fd)
4589 // fa'/fd' = minambient
4590 // fa'+0.25*fd' = fa+0.25*fd
4592 // fa' = fd' * minambient
4593 // fd'*(0.25+minambient) = fa+0.25*fd
4595 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4596 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4598 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4599 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
4600 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4601 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4606 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4608 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4609 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4613 // adjust brightness and saturation to target
4614 avg[0] = avg[1] = avg[2] = fa / f;
4615 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4616 avg[0] = avg[1] = avg[2] = fd / f;
4617 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4623 VectorSet(ent->modellight_ambient, 1, 1, 1);
4625 // move the light direction into modelspace coordinates for lighting code
4626 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4627 if(VectorLength2(ent->modellight_lightdir) == 0)
4628 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4629 VectorNormalize(ent->modellight_lightdir);
4633 #define MAX_LINEOFSIGHTTRACES 64
4635 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4638 vec3_t boxmins, boxmaxs;
4641 dp_model_t *model = r_refdef.scene.worldmodel;
4643 if (!model || !model->brush.TraceLineOfSight)
4646 // expand the box a little
4647 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4648 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4649 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4650 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4651 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4652 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4654 // return true if eye is inside enlarged box
4655 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4659 VectorCopy(eye, start);
4660 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4661 if (model->brush.TraceLineOfSight(model, start, end))
4664 // try various random positions
4665 for (i = 0;i < numsamples;i++)
4667 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4668 if (model->brush.TraceLineOfSight(model, start, end))
4676 static void R_View_UpdateEntityVisible (void)
4681 entity_render_t *ent;
4683 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4684 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4685 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4686 : RENDER_EXTERIORMODEL;
4687 if (!r_drawviewmodel.integer)
4688 renderimask |= RENDER_VIEWMODEL;
4689 if (!r_drawexteriormodel.integer)
4690 renderimask |= RENDER_EXTERIORMODEL;
4691 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4693 // worldmodel can check visibility
4694 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4695 for (i = 0;i < r_refdef.scene.numentities;i++)
4697 ent = r_refdef.scene.entities[i];
4698 if (!(ent->flags & renderimask))
4699 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)))
4700 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))
4701 r_refdef.viewcache.entityvisible[i] = true;
4703 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4704 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4706 for (i = 0;i < r_refdef.scene.numentities;i++)
4708 ent = r_refdef.scene.entities[i];
4709 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4711 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4713 continue; // temp entities do pvs only
4714 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4715 ent->last_trace_visibility = realtime;
4716 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4717 r_refdef.viewcache.entityvisible[i] = 0;
4724 // no worldmodel or it can't check visibility
4725 for (i = 0;i < r_refdef.scene.numentities;i++)
4727 ent = r_refdef.scene.entities[i];
4728 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));
4733 /// only used if skyrendermasked, and normally returns false
4734 int R_DrawBrushModelsSky (void)
4737 entity_render_t *ent;
4740 for (i = 0;i < r_refdef.scene.numentities;i++)
4742 if (!r_refdef.viewcache.entityvisible[i])
4744 ent = r_refdef.scene.entities[i];
4745 if (!ent->model || !ent->model->DrawSky)
4747 ent->model->DrawSky(ent);
4753 static void R_DrawNoModel(entity_render_t *ent);
4754 static void R_DrawModels(void)
4757 entity_render_t *ent;
4759 for (i = 0;i < r_refdef.scene.numentities;i++)
4761 if (!r_refdef.viewcache.entityvisible[i])
4763 ent = r_refdef.scene.entities[i];
4764 r_refdef.stats.entities++;
4765 if (ent->model && ent->model->Draw != NULL)
4766 ent->model->Draw(ent);
4772 static void R_DrawModelsDepth(void)
4775 entity_render_t *ent;
4777 for (i = 0;i < r_refdef.scene.numentities;i++)
4779 if (!r_refdef.viewcache.entityvisible[i])
4781 ent = r_refdef.scene.entities[i];
4782 if (ent->model && ent->model->DrawDepth != NULL)
4783 ent->model->DrawDepth(ent);
4787 static void R_DrawModelsDebug(void)
4790 entity_render_t *ent;
4792 for (i = 0;i < r_refdef.scene.numentities;i++)
4794 if (!r_refdef.viewcache.entityvisible[i])
4796 ent = r_refdef.scene.entities[i];
4797 if (ent->model && ent->model->DrawDebug != NULL)
4798 ent->model->DrawDebug(ent);
4802 static void R_DrawModelsAddWaterPlanes(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 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4813 ent->model->DrawAddWaterPlanes(ent);
4817 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4819 if (r_hdr_irisadaptation.integer)
4823 vec3_t diffusenormal;
4828 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4829 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4830 brightness = max(0.0000001f, brightness);
4831 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4832 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4833 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4834 current = r_hdr_irisadaptation_value.value;
4836 current = min(current + adjust, goal);
4837 else if (current > goal)
4838 current = max(current - adjust, goal);
4839 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4840 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4842 else if (r_hdr_irisadaptation_value.value != 1.0f)
4843 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4846 static void R_View_SetFrustum(const int *scissor)
4849 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4850 vec3_t forward, left, up, origin, v;
4854 // flipped x coordinates (because x points left here)
4855 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4856 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4858 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4859 switch(vid.renderpath)
4861 case RENDERPATH_D3D9:
4862 case RENDERPATH_D3D10:
4863 case RENDERPATH_D3D11:
4864 case RENDERPATH_SOFT:
4865 // non-flipped y coordinates
4866 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4867 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4869 case RENDERPATH_GL11:
4870 case RENDERPATH_GL13:
4871 case RENDERPATH_GL20:
4872 case RENDERPATH_GLES2:
4873 // non-flipped y coordinates
4874 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4875 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4880 // we can't trust r_refdef.view.forward and friends in reflected scenes
4881 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4884 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4885 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4886 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4887 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4888 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4889 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4890 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4891 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4892 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4893 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4894 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4895 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4899 zNear = r_refdef.nearclip;
4900 nudge = 1.0 - 1.0 / (1<<23);
4901 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4902 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4903 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4904 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4905 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4906 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4907 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4908 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4914 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4915 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4916 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4917 r_refdef.view.frustum[0].dist = m[15] - m[12];
4919 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4920 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4921 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4922 r_refdef.view.frustum[1].dist = m[15] + m[12];
4924 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4925 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4926 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4927 r_refdef.view.frustum[2].dist = m[15] - m[13];
4929 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4930 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4931 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4932 r_refdef.view.frustum[3].dist = m[15] + m[13];
4934 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4935 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4936 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4937 r_refdef.view.frustum[4].dist = m[15] - m[14];
4939 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4940 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4941 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4942 r_refdef.view.frustum[5].dist = m[15] + m[14];
4945 if (r_refdef.view.useperspective)
4947 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4948 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]);
4949 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]);
4950 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]);
4951 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]);
4953 // then the normals from the corners relative to origin
4954 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4955 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4956 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4957 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4959 // in a NORMAL view, forward cross left == up
4960 // in a REFLECTED view, forward cross left == down
4961 // so our cross products above need to be adjusted for a left handed coordinate system
4962 CrossProduct(forward, left, v);
4963 if(DotProduct(v, up) < 0)
4965 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4966 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
4967 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
4968 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
4971 // Leaving those out was a mistake, those were in the old code, and they
4972 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4973 // I couldn't reproduce it after adding those normalizations. --blub
4974 VectorNormalize(r_refdef.view.frustum[0].normal);
4975 VectorNormalize(r_refdef.view.frustum[1].normal);
4976 VectorNormalize(r_refdef.view.frustum[2].normal);
4977 VectorNormalize(r_refdef.view.frustum[3].normal);
4979 // make the corners absolute
4980 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
4981 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
4982 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
4983 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
4986 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4988 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4989 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4990 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4991 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4992 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4996 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
4997 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
4998 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
4999 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5000 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5001 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5002 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5003 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5004 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5005 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5007 r_refdef.view.numfrustumplanes = 5;
5009 if (r_refdef.view.useclipplane)
5011 r_refdef.view.numfrustumplanes = 6;
5012 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5015 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5016 PlaneClassify(r_refdef.view.frustum + i);
5018 // LordHavoc: note to all quake engine coders, Quake had a special case
5019 // for 90 degrees which assumed a square view (wrong), so I removed it,
5020 // Quake2 has it disabled as well.
5022 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5023 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5024 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5025 //PlaneClassify(&frustum[0]);
5027 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5028 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5029 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5030 //PlaneClassify(&frustum[1]);
5032 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5033 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5034 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5035 //PlaneClassify(&frustum[2]);
5037 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5038 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5039 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5040 //PlaneClassify(&frustum[3]);
5043 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5044 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5045 //PlaneClassify(&frustum[4]);
5048 void R_View_UpdateWithScissor(const int *myscissor)
5050 R_Main_ResizeViewCache();
5051 R_View_SetFrustum(myscissor);
5052 R_View_WorldVisibility(r_refdef.view.useclipplane);
5053 R_View_UpdateEntityVisible();
5054 R_View_UpdateEntityLighting();
5057 void R_View_Update(void)
5059 R_Main_ResizeViewCache();
5060 R_View_SetFrustum(NULL);
5061 R_View_WorldVisibility(r_refdef.view.useclipplane);
5062 R_View_UpdateEntityVisible();
5063 R_View_UpdateEntityLighting();
5066 void R_SetupView(qboolean allowwaterclippingplane)
5068 const float *customclipplane = NULL;
5070 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5072 // LordHavoc: couldn't figure out how to make this approach the
5073 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5074 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5075 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5076 dist = r_refdef.view.clipplane.dist;
5077 plane[0] = r_refdef.view.clipplane.normal[0];
5078 plane[1] = r_refdef.view.clipplane.normal[1];
5079 plane[2] = r_refdef.view.clipplane.normal[2];
5081 customclipplane = plane;
5084 if (!r_refdef.view.useperspective)
5085 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);
5086 else if (vid.stencil && r_useinfinitefarclip.integer)
5087 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);
5089 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);
5090 R_SetViewport(&r_refdef.view.viewport);
5093 void R_EntityMatrix(const matrix4x4_t *matrix)
5095 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5097 gl_modelmatrixchanged = false;
5098 gl_modelmatrix = *matrix;
5099 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5100 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5101 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5102 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5104 switch(vid.renderpath)
5106 case RENDERPATH_D3D9:
5108 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5109 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5112 case RENDERPATH_D3D10:
5113 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5115 case RENDERPATH_D3D11:
5116 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5118 case RENDERPATH_GL13:
5119 case RENDERPATH_GL11:
5120 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5122 case RENDERPATH_SOFT:
5123 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5124 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5126 case RENDERPATH_GL20:
5127 case RENDERPATH_GLES2:
5128 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5129 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5135 void R_ResetViewRendering2D(void)
5137 r_viewport_t viewport;
5140 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5141 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);
5142 R_SetViewport(&viewport);
5143 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5144 GL_Color(1, 1, 1, 1);
5145 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5146 GL_BlendFunc(GL_ONE, GL_ZERO);
5147 GL_ScissorTest(false);
5148 GL_DepthMask(false);
5149 GL_DepthRange(0, 1);
5150 GL_DepthTest(false);
5151 GL_DepthFunc(GL_LEQUAL);
5152 R_EntityMatrix(&identitymatrix);
5153 R_Mesh_ResetTextureState();
5154 GL_PolygonOffset(0, 0);
5155 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5156 switch(vid.renderpath)
5158 case RENDERPATH_GL11:
5159 case RENDERPATH_GL13:
5160 case RENDERPATH_GL20:
5161 case RENDERPATH_GLES2:
5162 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5164 case RENDERPATH_D3D9:
5165 case RENDERPATH_D3D10:
5166 case RENDERPATH_D3D11:
5167 case RENDERPATH_SOFT:
5170 GL_CullFace(GL_NONE);
5173 void R_ResetViewRendering3D(void)
5178 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5179 GL_Color(1, 1, 1, 1);
5180 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5181 GL_BlendFunc(GL_ONE, GL_ZERO);
5182 GL_ScissorTest(true);
5184 GL_DepthRange(0, 1);
5186 GL_DepthFunc(GL_LEQUAL);
5187 R_EntityMatrix(&identitymatrix);
5188 R_Mesh_ResetTextureState();
5189 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5190 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5191 switch(vid.renderpath)
5193 case RENDERPATH_GL11:
5194 case RENDERPATH_GL13:
5195 case RENDERPATH_GL20:
5196 case RENDERPATH_GLES2:
5197 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5199 case RENDERPATH_D3D9:
5200 case RENDERPATH_D3D10:
5201 case RENDERPATH_D3D11:
5202 case RENDERPATH_SOFT:
5205 GL_CullFace(r_refdef.view.cullface_back);
5210 R_RenderView_UpdateViewVectors
5213 static void R_RenderView_UpdateViewVectors(void)
5215 // break apart the view matrix into vectors for various purposes
5216 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5217 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5218 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5219 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5220 // make an inverted copy of the view matrix for tracking sprites
5221 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5224 void R_RenderScene(void);
5225 void R_RenderWaterPlanes(void);
5227 static void R_Water_StartFrame(void)
5230 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5231 r_waterstate_waterplane_t *p;
5233 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5236 switch(vid.renderpath)
5238 case RENDERPATH_GL20:
5239 case RENDERPATH_D3D9:
5240 case RENDERPATH_D3D10:
5241 case RENDERPATH_D3D11:
5242 case RENDERPATH_SOFT:
5243 case RENDERPATH_GLES2:
5245 case RENDERPATH_GL13:
5246 case RENDERPATH_GL11:
5250 // set waterwidth and waterheight to the water resolution that will be
5251 // used (often less than the screen resolution for faster rendering)
5252 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5253 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5255 // calculate desired texture sizes
5256 // can't use water if the card does not support the texture size
5257 if (!r_water.integer || r_showsurfaces.integer)
5258 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5259 else if (vid.support.arb_texture_non_power_of_two)
5261 texturewidth = waterwidth;
5262 textureheight = waterheight;
5263 camerawidth = waterwidth;
5264 cameraheight = waterheight;
5268 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5269 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5270 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5271 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5274 // allocate textures as needed
5275 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5277 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5278 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5280 if (p->texture_refraction)
5281 R_FreeTexture(p->texture_refraction);
5282 p->texture_refraction = NULL;
5283 if (p->texture_reflection)
5284 R_FreeTexture(p->texture_reflection);
5285 p->texture_reflection = NULL;
5286 if (p->texture_camera)
5287 R_FreeTexture(p->texture_camera);
5288 p->texture_camera = NULL;
5290 memset(&r_waterstate, 0, sizeof(r_waterstate));
5291 r_waterstate.texturewidth = texturewidth;
5292 r_waterstate.textureheight = textureheight;
5293 r_waterstate.camerawidth = camerawidth;
5294 r_waterstate.cameraheight = cameraheight;
5297 if (r_waterstate.texturewidth)
5299 r_waterstate.enabled = true;
5301 // when doing a reduced render (HDR) we want to use a smaller area
5302 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5303 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5305 // set up variables that will be used in shader setup
5306 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5307 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5308 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5309 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5312 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5313 r_waterstate.numwaterplanes = 0;
5316 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5318 int triangleindex, planeindex;
5324 r_waterstate_waterplane_t *p;
5325 texture_t *t = R_GetCurrentTexture(surface->texture);
5327 // just use the first triangle with a valid normal for any decisions
5328 VectorClear(normal);
5329 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5331 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5332 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5333 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5334 TriangleNormal(vert[0], vert[1], vert[2], normal);
5335 if (VectorLength2(normal) >= 0.001)
5339 VectorCopy(normal, plane.normal);
5340 VectorNormalize(plane.normal);
5341 plane.dist = DotProduct(vert[0], plane.normal);
5342 PlaneClassify(&plane);
5343 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5345 // skip backfaces (except if nocullface is set)
5346 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5348 VectorNegate(plane.normal, plane.normal);
5350 PlaneClassify(&plane);
5354 // find a matching plane if there is one
5355 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5356 if(p->camera_entity == t->camera_entity)
5357 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5359 if (planeindex >= r_waterstate.maxwaterplanes)
5360 return; // nothing we can do, out of planes
5362 // if this triangle does not fit any known plane rendered this frame, add one
5363 if (planeindex >= r_waterstate.numwaterplanes)
5365 // store the new plane
5366 r_waterstate.numwaterplanes++;
5368 // clear materialflags and pvs
5369 p->materialflags = 0;
5370 p->pvsvalid = false;
5371 p->camera_entity = t->camera_entity;
5372 VectorCopy(surface->mins, p->mins);
5373 VectorCopy(surface->maxs, p->maxs);
5378 p->mins[0] = min(p->mins[0], surface->mins[0]);
5379 p->mins[1] = min(p->mins[1], surface->mins[1]);
5380 p->mins[2] = min(p->mins[2], surface->mins[2]);
5381 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5382 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5383 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5385 // merge this surface's materialflags into the waterplane
5386 p->materialflags |= t->currentmaterialflags;
5387 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5389 // merge this surface's PVS into the waterplane
5390 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5391 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5392 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5394 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5400 static void R_Water_ProcessPlanes(void)
5403 r_refdef_view_t originalview;
5404 r_refdef_view_t myview;
5406 r_waterstate_waterplane_t *p;
5409 originalview = r_refdef.view;
5411 // make sure enough textures are allocated
5412 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5414 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5416 if (!p->texture_refraction)
5417 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);
5418 if (!p->texture_refraction)
5421 else if (p->materialflags & MATERIALFLAG_CAMERA)
5423 if (!p->texture_camera)
5424 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);
5425 if (!p->texture_camera)
5429 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5431 if (!p->texture_reflection)
5432 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);
5433 if (!p->texture_reflection)
5439 r_refdef.view = originalview;
5440 r_refdef.view.showdebug = false;
5441 r_refdef.view.width = r_waterstate.waterwidth;
5442 r_refdef.view.height = r_waterstate.waterheight;
5443 r_refdef.view.useclipplane = true;
5444 myview = r_refdef.view;
5445 r_waterstate.renderingscene = true;
5446 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5448 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5450 r_refdef.view = myview;
5451 if(r_water_scissormode.integer)
5454 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5455 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5458 // render reflected scene and copy into texture
5459 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5460 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5461 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5462 r_refdef.view.clipplane = p->plane;
5464 // reverse the cullface settings for this render
5465 r_refdef.view.cullface_front = GL_FRONT;
5466 r_refdef.view.cullface_back = GL_BACK;
5467 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5469 r_refdef.view.usecustompvs = true;
5471 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5473 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5476 R_ResetViewRendering3D();
5477 R_ClearScreen(r_refdef.fogenabled);
5478 if(r_water_scissormode.integer & 2)
5479 R_View_UpdateWithScissor(myscissor);
5482 if(r_water_scissormode.integer & 1)
5483 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5486 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);
5489 // render the normal view scene and copy into texture
5490 // (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)
5491 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5493 r_refdef.view = myview;
5494 if(r_water_scissormode.integer)
5497 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5498 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5501 r_waterstate.renderingrefraction = true;
5503 r_refdef.view.clipplane = p->plane;
5504 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5505 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5507 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5509 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5510 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5511 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5512 R_RenderView_UpdateViewVectors();
5513 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5515 r_refdef.view.usecustompvs = true;
5516 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);
5520 PlaneClassify(&r_refdef.view.clipplane);
5522 R_ResetViewRendering3D();
5523 R_ClearScreen(r_refdef.fogenabled);
5524 if(r_water_scissormode.integer & 2)
5525 R_View_UpdateWithScissor(myscissor);
5528 if(r_water_scissormode.integer & 1)
5529 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5532 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);
5533 r_waterstate.renderingrefraction = false;
5535 else if (p->materialflags & MATERIALFLAG_CAMERA)
5537 r_refdef.view = myview;
5539 r_refdef.view.clipplane = p->plane;
5540 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5541 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5543 r_refdef.view.width = r_waterstate.camerawidth;
5544 r_refdef.view.height = r_waterstate.cameraheight;
5545 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5546 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5548 if(p->camera_entity)
5550 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5551 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5554 // note: all of the view is used for displaying... so
5555 // there is no use in scissoring
5557 // reverse the cullface settings for this render
5558 r_refdef.view.cullface_front = GL_FRONT;
5559 r_refdef.view.cullface_back = GL_BACK;
5560 // also reverse the view matrix
5561 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
5562 R_RenderView_UpdateViewVectors();
5563 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5565 r_refdef.view.usecustompvs = true;
5566 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);
5569 // camera needs no clipplane
5570 r_refdef.view.useclipplane = false;
5572 PlaneClassify(&r_refdef.view.clipplane);
5574 R_ResetViewRendering3D();
5575 R_ClearScreen(r_refdef.fogenabled);
5579 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);
5580 r_waterstate.renderingrefraction = false;
5584 r_waterstate.renderingscene = false;
5585 r_refdef.view = originalview;
5586 R_ResetViewRendering3D();
5587 R_ClearScreen(r_refdef.fogenabled);
5591 r_refdef.view = originalview;
5592 r_waterstate.renderingscene = false;
5593 Cvar_SetValueQuick(&r_water, 0);
5594 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5598 void R_Bloom_StartFrame(void)
5600 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5602 switch(vid.renderpath)
5604 case RENDERPATH_GL20:
5605 case RENDERPATH_D3D9:
5606 case RENDERPATH_D3D10:
5607 case RENDERPATH_D3D11:
5608 case RENDERPATH_SOFT:
5609 case RENDERPATH_GLES2:
5611 case RENDERPATH_GL13:
5612 case RENDERPATH_GL11:
5616 // set bloomwidth and bloomheight to the bloom resolution that will be
5617 // used (often less than the screen resolution for faster rendering)
5618 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5619 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5620 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5621 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5622 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5624 // calculate desired texture sizes
5625 if (vid.support.arb_texture_non_power_of_two)
5627 screentexturewidth = r_refdef.view.width;
5628 screentextureheight = r_refdef.view.height;
5629 bloomtexturewidth = r_bloomstate.bloomwidth;
5630 bloomtextureheight = r_bloomstate.bloomheight;
5634 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5635 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5636 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5637 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5640 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))
5642 Cvar_SetValueQuick(&r_hdr, 0);
5643 Cvar_SetValueQuick(&r_bloom, 0);
5644 Cvar_SetValueQuick(&r_motionblur, 0);
5645 Cvar_SetValueQuick(&r_damageblur, 0);
5648 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)))
5649 screentexturewidth = screentextureheight = 0;
5650 if (!r_hdr.integer && !r_bloom.integer)
5651 bloomtexturewidth = bloomtextureheight = 0;
5653 // allocate textures as needed
5654 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5656 if (r_bloomstate.texture_screen)
5657 R_FreeTexture(r_bloomstate.texture_screen);
5658 r_bloomstate.texture_screen = NULL;
5659 r_bloomstate.screentexturewidth = screentexturewidth;
5660 r_bloomstate.screentextureheight = screentextureheight;
5661 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5662 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);
5664 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5666 if (r_bloomstate.texture_bloom)
5667 R_FreeTexture(r_bloomstate.texture_bloom);
5668 r_bloomstate.texture_bloom = NULL;
5669 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5670 r_bloomstate.bloomtextureheight = bloomtextureheight;
5671 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5672 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);
5675 // when doing a reduced render (HDR) we want to use a smaller area
5676 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5677 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5678 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5679 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5680 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5682 // set up a texcoord array for the full resolution screen image
5683 // (we have to keep this around to copy back during final render)
5684 r_bloomstate.screentexcoord2f[0] = 0;
5685 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5686 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5687 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5688 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5689 r_bloomstate.screentexcoord2f[5] = 0;
5690 r_bloomstate.screentexcoord2f[6] = 0;
5691 r_bloomstate.screentexcoord2f[7] = 0;
5693 // set up a texcoord array for the reduced resolution bloom image
5694 // (which will be additive blended over the screen image)
5695 r_bloomstate.bloomtexcoord2f[0] = 0;
5696 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5697 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5698 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5699 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5700 r_bloomstate.bloomtexcoord2f[5] = 0;
5701 r_bloomstate.bloomtexcoord2f[6] = 0;
5702 r_bloomstate.bloomtexcoord2f[7] = 0;
5704 switch(vid.renderpath)
5706 case RENDERPATH_GL11:
5707 case RENDERPATH_GL13:
5708 case RENDERPATH_GL20:
5709 case RENDERPATH_SOFT:
5710 case RENDERPATH_GLES2:
5712 case RENDERPATH_D3D9:
5713 case RENDERPATH_D3D10:
5714 case RENDERPATH_D3D11:
5717 for (i = 0;i < 4;i++)
5719 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5720 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5721 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5722 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5728 if (r_hdr.integer || r_bloom.integer)
5730 r_bloomstate.enabled = true;
5731 r_bloomstate.hdr = r_hdr.integer != 0;
5734 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);
5737 void R_Bloom_CopyBloomTexture(float colorscale)
5739 r_refdef.stats.bloom++;
5741 // scale down screen texture to the bloom texture size
5743 R_SetViewport(&r_bloomstate.viewport);
5744 GL_BlendFunc(GL_ONE, GL_ZERO);
5745 GL_Color(colorscale, colorscale, colorscale, 1);
5746 // 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...
5747 switch(vid.renderpath)
5749 case RENDERPATH_GL11:
5750 case RENDERPATH_GL13:
5751 case RENDERPATH_GL20:
5752 case RENDERPATH_SOFT:
5753 case RENDERPATH_GLES2:
5754 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5756 case RENDERPATH_D3D9:
5757 case RENDERPATH_D3D10:
5758 case RENDERPATH_D3D11:
5759 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5762 // TODO: do boxfilter scale-down in shader?
5763 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5764 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5765 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5767 // we now have a bloom image in the framebuffer
5768 // copy it into the bloom image texture for later processing
5769 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);
5770 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5773 void R_Bloom_CopyHDRTexture(void)
5775 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);
5776 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5779 void R_Bloom_MakeTexture(void)
5782 float xoffset, yoffset, r, brighten;
5784 r_refdef.stats.bloom++;
5786 R_ResetViewRendering2D();
5788 // we have a bloom image in the framebuffer
5790 R_SetViewport(&r_bloomstate.viewport);
5792 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5795 r = bound(0, r_bloom_colorexponent.value / x, 1);
5796 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5798 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5799 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5800 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5801 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5803 // copy the vertically blurred bloom view to a texture
5804 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);
5805 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5808 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5809 brighten = r_bloom_brighten.value;
5811 brighten *= r_hdr_range.value;
5812 brighten = sqrt(brighten);
5814 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5815 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5817 for (dir = 0;dir < 2;dir++)
5819 // blend on at multiple vertical offsets to achieve a vertical blur
5820 // TODO: do offset blends using GLSL
5821 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5822 GL_BlendFunc(GL_ONE, GL_ZERO);
5823 for (x = -range;x <= range;x++)
5825 if (!dir){xoffset = 0;yoffset = x;}
5826 else {xoffset = x;yoffset = 0;}
5827 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5828 yoffset /= (float)r_bloomstate.bloomtextureheight;
5829 // compute a texcoord array with the specified x and y offset
5830 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5831 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5832 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5833 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5834 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5835 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5836 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5837 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5838 // this r value looks like a 'dot' particle, fading sharply to
5839 // black at the edges
5840 // (probably not realistic but looks good enough)
5841 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5842 //r = brighten/(range*2+1);
5843 r = brighten / (range * 2 + 1);
5845 r *= (1 - x*x/(float)(range*range));
5846 GL_Color(r, r, r, 1);
5847 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
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;
5850 GL_BlendFunc(GL_ONE, GL_ONE);
5853 // copy the vertically blurred bloom view to a texture
5854 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);
5855 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5859 void R_HDR_RenderBloomTexture(void)
5861 int oldwidth, oldheight;
5862 float oldcolorscale;
5863 qboolean oldwaterstate;
5865 oldwaterstate = r_waterstate.enabled;
5866 oldcolorscale = r_refdef.view.colorscale;
5867 oldwidth = r_refdef.view.width;
5868 oldheight = r_refdef.view.height;
5869 r_refdef.view.width = r_bloomstate.bloomwidth;
5870 r_refdef.view.height = r_bloomstate.bloomheight;
5872 if(r_hdr.integer < 2)
5873 r_waterstate.enabled = false;
5875 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5876 // TODO: add exposure compensation features
5877 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5879 r_refdef.view.showdebug = false;
5880 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5882 R_ResetViewRendering3D();
5884 R_ClearScreen(r_refdef.fogenabled);
5885 if (r_timereport_active)
5886 R_TimeReport("HDRclear");
5889 if (r_timereport_active)
5890 R_TimeReport("visibility");
5892 // only do secondary renders with HDR if r_hdr is 2 or higher
5893 r_waterstate.numwaterplanes = 0;
5894 if (r_waterstate.enabled)
5895 R_RenderWaterPlanes();
5897 r_refdef.view.showdebug = true;
5899 r_waterstate.numwaterplanes = 0;
5901 R_ResetViewRendering2D();
5903 R_Bloom_CopyHDRTexture();
5904 R_Bloom_MakeTexture();
5906 // restore the view settings
5907 r_waterstate.enabled = oldwaterstate;
5908 r_refdef.view.width = oldwidth;
5909 r_refdef.view.height = oldheight;
5910 r_refdef.view.colorscale = oldcolorscale;
5912 R_ResetViewRendering3D();
5914 R_ClearScreen(r_refdef.fogenabled);
5915 if (r_timereport_active)
5916 R_TimeReport("viewclear");
5919 static void R_BlendView(void)
5921 unsigned int permutation;
5922 float uservecs[4][4];
5924 switch (vid.renderpath)
5926 case RENDERPATH_GL20:
5927 case RENDERPATH_D3D9:
5928 case RENDERPATH_D3D10:
5929 case RENDERPATH_D3D11:
5930 case RENDERPATH_SOFT:
5931 case RENDERPATH_GLES2:
5933 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5934 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5935 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5936 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5937 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5939 if (r_bloomstate.texture_screen)
5941 // make sure the buffer is available
5942 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5944 R_ResetViewRendering2D();
5946 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5948 // declare variables
5950 static float avgspeed;
5952 speed = VectorLength(cl.movement_velocity);
5954 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5955 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5957 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5958 speed = bound(0, speed, 1);
5959 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5961 // calculate values into a standard alpha
5962 cl.motionbluralpha = 1 - exp(-
5964 (r_motionblur.value * speed / 80)
5966 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5969 max(0.0001, cl.time - cl.oldtime) // fps independent
5972 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5973 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5975 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
5977 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5978 GL_Color(1, 1, 1, cl.motionbluralpha);
5979 switch(vid.renderpath)
5981 case RENDERPATH_GL11:
5982 case RENDERPATH_GL13:
5983 case RENDERPATH_GL20:
5984 case RENDERPATH_SOFT:
5985 case RENDERPATH_GLES2:
5986 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5988 case RENDERPATH_D3D9:
5989 case RENDERPATH_D3D10:
5990 case RENDERPATH_D3D11:
5991 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5994 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5995 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5996 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6000 // copy view into the screen texture
6001 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);
6002 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6004 else if (!r_bloomstate.texture_bloom)
6006 // we may still have to do view tint...
6007 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6009 // apply a color tint to the whole view
6010 R_ResetViewRendering2D();
6011 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6012 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6013 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6014 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6015 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6017 break; // no screen processing, no bloom, skip it
6020 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6022 // render simple bloom effect
6023 // copy the screen and shrink it and darken it for the bloom process
6024 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6025 // make the bloom texture
6026 R_Bloom_MakeTexture();
6029 #if _MSC_VER >= 1400
6030 #define sscanf sscanf_s
6032 memset(uservecs, 0, sizeof(uservecs));
6033 if (r_glsl_postprocess_uservec1_enable.integer)
6034 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6035 if (r_glsl_postprocess_uservec2_enable.integer)
6036 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6037 if (r_glsl_postprocess_uservec3_enable.integer)
6038 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6039 if (r_glsl_postprocess_uservec4_enable.integer)
6040 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6042 R_ResetViewRendering2D();
6043 GL_Color(1, 1, 1, 1);
6044 GL_BlendFunc(GL_ONE, GL_ZERO);
6046 switch(vid.renderpath)
6048 case RENDERPATH_GL20:
6049 case RENDERPATH_GLES2:
6050 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6051 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6052 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6053 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6054 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6055 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]);
6056 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6057 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]);
6058 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]);
6059 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]);
6060 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]);
6061 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6062 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6063 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);
6065 case RENDERPATH_D3D9:
6067 // 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...
6068 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6069 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6070 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6071 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6072 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6073 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6074 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6075 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6076 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6077 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6078 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6079 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6080 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6081 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6084 case RENDERPATH_D3D10:
6085 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6087 case RENDERPATH_D3D11:
6088 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6090 case RENDERPATH_SOFT:
6091 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6092 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6093 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6094 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6095 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6096 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6097 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6098 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6099 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6100 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6101 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6102 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6103 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6104 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6109 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6110 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6112 case RENDERPATH_GL13:
6113 case RENDERPATH_GL11:
6114 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6116 // apply a color tint to the whole view
6117 R_ResetViewRendering2D();
6118 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6119 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6120 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6121 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6122 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6128 matrix4x4_t r_waterscrollmatrix;
6130 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6132 if (r_refdef.fog_density)
6134 r_refdef.fogcolor[0] = r_refdef.fog_red;
6135 r_refdef.fogcolor[1] = r_refdef.fog_green;
6136 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6138 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6139 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6140 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6141 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6145 VectorCopy(r_refdef.fogcolor, fogvec);
6146 // color.rgb *= ContrastBoost * SceneBrightness;
6147 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6148 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6149 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6150 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6155 void R_UpdateVariables(void)
6159 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6161 r_refdef.farclip = r_farclip_base.value;
6162 if (r_refdef.scene.worldmodel)
6163 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6164 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6166 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6167 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6168 r_refdef.polygonfactor = 0;
6169 r_refdef.polygonoffset = 0;
6170 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6171 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6173 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6174 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6175 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6176 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6177 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6178 if (FAKELIGHT_ENABLED)
6180 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6182 if (r_showsurfaces.integer)
6184 r_refdef.scene.rtworld = false;
6185 r_refdef.scene.rtworldshadows = false;
6186 r_refdef.scene.rtdlight = false;
6187 r_refdef.scene.rtdlightshadows = false;
6188 r_refdef.lightmapintensity = 0;
6191 if (gamemode == GAME_NEHAHRA)
6193 if (gl_fogenable.integer)
6195 r_refdef.oldgl_fogenable = true;
6196 r_refdef.fog_density = gl_fogdensity.value;
6197 r_refdef.fog_red = gl_fogred.value;
6198 r_refdef.fog_green = gl_foggreen.value;
6199 r_refdef.fog_blue = gl_fogblue.value;
6200 r_refdef.fog_alpha = 1;
6201 r_refdef.fog_start = 0;
6202 r_refdef.fog_end = gl_skyclip.value;
6203 r_refdef.fog_height = 1<<30;
6204 r_refdef.fog_fadedepth = 128;
6206 else if (r_refdef.oldgl_fogenable)
6208 r_refdef.oldgl_fogenable = false;
6209 r_refdef.fog_density = 0;
6210 r_refdef.fog_red = 0;
6211 r_refdef.fog_green = 0;
6212 r_refdef.fog_blue = 0;
6213 r_refdef.fog_alpha = 0;
6214 r_refdef.fog_start = 0;
6215 r_refdef.fog_end = 0;
6216 r_refdef.fog_height = 1<<30;
6217 r_refdef.fog_fadedepth = 128;
6221 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6222 r_refdef.fog_start = max(0, r_refdef.fog_start);
6223 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6225 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6227 if (r_refdef.fog_density && r_drawfog.integer)
6229 r_refdef.fogenabled = true;
6230 // this is the point where the fog reaches 0.9986 alpha, which we
6231 // consider a good enough cutoff point for the texture
6232 // (0.9986 * 256 == 255.6)
6233 if (r_fog_exp2.integer)
6234 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6236 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6237 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6238 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6239 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6240 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6241 R_BuildFogHeightTexture();
6242 // fog color was already set
6243 // update the fog texture
6244 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)
6245 R_BuildFogTexture();
6246 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6247 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6250 r_refdef.fogenabled = false;
6252 switch(vid.renderpath)
6254 case RENDERPATH_GL20:
6255 case RENDERPATH_D3D9:
6256 case RENDERPATH_D3D10:
6257 case RENDERPATH_D3D11:
6258 case RENDERPATH_SOFT:
6259 case RENDERPATH_GLES2:
6260 if(v_glslgamma.integer && !vid_gammatables_trivial)
6262 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6264 // build GLSL gamma texture
6265 #define RAMPWIDTH 256
6266 unsigned short ramp[RAMPWIDTH * 3];
6267 unsigned char rampbgr[RAMPWIDTH][4];
6270 r_texture_gammaramps_serial = vid_gammatables_serial;
6272 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6273 for(i = 0; i < RAMPWIDTH; ++i)
6275 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6276 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6277 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6280 if (r_texture_gammaramps)
6282 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6286 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6292 // remove GLSL gamma texture
6295 case RENDERPATH_GL13:
6296 case RENDERPATH_GL11:
6301 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6302 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6308 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6309 if( scenetype != r_currentscenetype ) {
6310 // store the old scenetype
6311 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6312 r_currentscenetype = scenetype;
6313 // move in the new scene
6314 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6323 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6325 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6326 if( scenetype == r_currentscenetype ) {
6327 return &r_refdef.scene;
6329 return &r_scenes_store[ scenetype ];
6338 int dpsoftrast_test;
6339 void R_RenderView(void)
6341 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6343 dpsoftrast_test = r_test.integer;
6345 if (r_timereport_active)
6346 R_TimeReport("start");
6347 r_textureframe++; // used only by R_GetCurrentTexture
6348 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6350 if(R_CompileShader_CheckStaticParms())
6353 if (!r_drawentities.integer)
6354 r_refdef.scene.numentities = 0;
6356 R_AnimCache_ClearCache();
6357 R_FrameData_NewFrame();
6359 /* adjust for stereo display */
6360 if(R_Stereo_Active())
6362 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);
6363 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6366 if (r_refdef.view.isoverlay)
6368 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6369 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6370 R_TimeReport("depthclear");
6372 r_refdef.view.showdebug = false;
6374 r_waterstate.enabled = false;
6375 r_waterstate.numwaterplanes = 0;
6379 r_refdef.view.matrix = originalmatrix;
6385 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6387 r_refdef.view.matrix = originalmatrix;
6388 return; //Host_Error ("R_RenderView: NULL worldmodel");
6391 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6393 R_RenderView_UpdateViewVectors();
6395 R_Shadow_UpdateWorldLightSelection();
6397 R_Bloom_StartFrame();
6398 R_Water_StartFrame();
6401 if (r_timereport_active)
6402 R_TimeReport("viewsetup");
6404 R_ResetViewRendering3D();
6406 if (r_refdef.view.clear || r_refdef.fogenabled)
6408 R_ClearScreen(r_refdef.fogenabled);
6409 if (r_timereport_active)
6410 R_TimeReport("viewclear");
6412 r_refdef.view.clear = true;
6414 // this produces a bloom texture to be used in R_BlendView() later
6415 if (r_hdr.integer && r_bloomstate.bloomwidth)
6417 R_HDR_RenderBloomTexture();
6418 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6419 r_textureframe++; // used only by R_GetCurrentTexture
6422 r_refdef.view.showdebug = true;
6425 if (r_timereport_active)
6426 R_TimeReport("visibility");
6428 r_waterstate.numwaterplanes = 0;
6429 if (r_waterstate.enabled)
6430 R_RenderWaterPlanes();
6433 r_waterstate.numwaterplanes = 0;
6436 if (r_timereport_active)
6437 R_TimeReport("blendview");
6439 GL_Scissor(0, 0, vid.width, vid.height);
6440 GL_ScissorTest(false);
6442 r_refdef.view.matrix = originalmatrix;
6447 void R_RenderWaterPlanes(void)
6449 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6451 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6452 if (r_timereport_active)
6453 R_TimeReport("waterworld");
6456 // don't let sound skip if going slow
6457 if (r_refdef.scene.extraupdate)
6460 R_DrawModelsAddWaterPlanes();
6461 if (r_timereport_active)
6462 R_TimeReport("watermodels");
6464 if (r_waterstate.numwaterplanes)
6466 R_Water_ProcessPlanes();
6467 if (r_timereport_active)
6468 R_TimeReport("waterscenes");
6472 extern void R_DrawLightningBeams (void);
6473 extern void VM_CL_AddPolygonsToMeshQueue (void);
6474 extern void R_DrawPortals (void);
6475 extern cvar_t cl_locs_show;
6476 static void R_DrawLocs(void);
6477 static void R_DrawEntityBBoxes(void);
6478 static void R_DrawModelDecals(void);
6479 extern void R_DrawModelShadows(void);
6480 extern void R_DrawModelShadowMaps(void);
6481 extern cvar_t cl_decals_newsystem;
6482 extern qboolean r_shadow_usingdeferredprepass;
6483 void R_RenderScene(void)
6485 qboolean shadowmapping = false;
6487 if (r_timereport_active)
6488 R_TimeReport("beginscene");
6490 r_refdef.stats.renders++;
6494 // don't let sound skip if going slow
6495 if (r_refdef.scene.extraupdate)
6498 R_MeshQueue_BeginScene();
6502 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);
6504 if (r_timereport_active)
6505 R_TimeReport("skystartframe");
6507 if (cl.csqc_vidvars.drawworld)
6509 // don't let sound skip if going slow
6510 if (r_refdef.scene.extraupdate)
6513 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6515 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6516 if (r_timereport_active)
6517 R_TimeReport("worldsky");
6520 if (R_DrawBrushModelsSky() && r_timereport_active)
6521 R_TimeReport("bmodelsky");
6523 if (skyrendermasked && skyrenderlater)
6525 // we have to force off the water clipping plane while rendering sky
6529 if (r_timereport_active)
6530 R_TimeReport("sky");
6534 R_AnimCache_CacheVisibleEntities();
6535 if (r_timereport_active)
6536 R_TimeReport("animation");
6538 R_Shadow_PrepareLights();
6539 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6540 R_Shadow_PrepareModelShadows();
6541 if (r_timereport_active)
6542 R_TimeReport("preparelights");
6544 if (R_Shadow_ShadowMappingEnabled())
6545 shadowmapping = true;
6547 if (r_shadow_usingdeferredprepass)
6548 R_Shadow_DrawPrepass();
6550 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6552 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6553 if (r_timereport_active)
6554 R_TimeReport("worlddepth");
6556 if (r_depthfirst.integer >= 2)
6558 R_DrawModelsDepth();
6559 if (r_timereport_active)
6560 R_TimeReport("modeldepth");
6563 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6565 R_DrawModelShadowMaps();
6566 R_ResetViewRendering3D();
6567 // don't let sound skip if going slow
6568 if (r_refdef.scene.extraupdate)
6572 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6574 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6575 if (r_timereport_active)
6576 R_TimeReport("world");
6579 // don't let sound skip if going slow
6580 if (r_refdef.scene.extraupdate)
6584 if (r_timereport_active)
6585 R_TimeReport("models");
6587 // don't let sound skip if going slow
6588 if (r_refdef.scene.extraupdate)
6591 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6593 R_DrawModelShadows();
6594 R_ResetViewRendering3D();
6595 // don't let sound skip if going slow
6596 if (r_refdef.scene.extraupdate)
6600 if (!r_shadow_usingdeferredprepass)
6602 R_Shadow_DrawLights();
6603 if (r_timereport_active)
6604 R_TimeReport("rtlights");
6607 // don't let sound skip if going slow
6608 if (r_refdef.scene.extraupdate)
6611 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6613 R_DrawModelShadows();
6614 R_ResetViewRendering3D();
6615 // don't let sound skip if going slow
6616 if (r_refdef.scene.extraupdate)
6620 if (cl.csqc_vidvars.drawworld)
6622 if (cl_decals_newsystem.integer)
6624 R_DrawModelDecals();
6625 if (r_timereport_active)
6626 R_TimeReport("modeldecals");
6631 if (r_timereport_active)
6632 R_TimeReport("decals");
6636 if (r_timereport_active)
6637 R_TimeReport("particles");
6640 if (r_timereport_active)
6641 R_TimeReport("explosions");
6643 R_DrawLightningBeams();
6644 if (r_timereport_active)
6645 R_TimeReport("lightning");
6648 VM_CL_AddPolygonsToMeshQueue();
6650 if (r_refdef.view.showdebug)
6652 if (cl_locs_show.integer)
6655 if (r_timereport_active)
6656 R_TimeReport("showlocs");
6659 if (r_drawportals.integer)
6662 if (r_timereport_active)
6663 R_TimeReport("portals");
6666 if (r_showbboxes.value > 0)
6668 R_DrawEntityBBoxes();
6669 if (r_timereport_active)
6670 R_TimeReport("bboxes");
6674 R_MeshQueue_RenderTransparent();
6675 if (r_timereport_active)
6676 R_TimeReport("drawtrans");
6678 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))
6680 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6681 if (r_timereport_active)
6682 R_TimeReport("worlddebug");
6683 R_DrawModelsDebug();
6684 if (r_timereport_active)
6685 R_TimeReport("modeldebug");
6688 if (cl.csqc_vidvars.drawworld)
6690 R_Shadow_DrawCoronas();
6691 if (r_timereport_active)
6692 R_TimeReport("coronas");
6697 GL_DepthTest(false);
6698 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6699 GL_Color(1, 1, 1, 1);
6700 qglBegin(GL_POLYGON);
6701 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6702 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6703 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6704 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6706 qglBegin(GL_POLYGON);
6707 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]);
6708 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]);
6709 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]);
6710 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]);
6712 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6716 // don't let sound skip if going slow
6717 if (r_refdef.scene.extraupdate)
6720 R_ResetViewRendering2D();
6723 static const unsigned short bboxelements[36] =
6733 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6736 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6738 RSurf_ActiveWorldEntity();
6740 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6741 GL_DepthMask(false);
6742 GL_DepthRange(0, 1);
6743 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6744 // R_Mesh_ResetTextureState();
6746 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6747 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6748 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6749 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6750 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6751 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6752 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6753 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6754 R_FillColors(color4f, 8, cr, cg, cb, ca);
6755 if (r_refdef.fogenabled)
6757 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6759 f1 = RSurf_FogVertex(v);
6761 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6762 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6763 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6766 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6767 R_Mesh_ResetTextureState();
6768 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6769 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6772 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6776 prvm_edict_t *edict;
6777 prvm_prog_t *prog_save = prog;
6779 // this function draws bounding boxes of server entities
6783 GL_CullFace(GL_NONE);
6784 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6788 for (i = 0;i < numsurfaces;i++)
6790 edict = PRVM_EDICT_NUM(surfacelist[i]);
6791 switch ((int)edict->fields.server->solid)
6793 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6794 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6795 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6796 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6797 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6798 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6800 color[3] *= r_showbboxes.value;
6801 color[3] = bound(0, color[3], 1);
6802 GL_DepthTest(!r_showdisabledepthtest.integer);
6803 GL_CullFace(r_refdef.view.cullface_front);
6804 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6810 static void R_DrawEntityBBoxes(void)
6813 prvm_edict_t *edict;
6815 prvm_prog_t *prog_save = prog;
6817 // this function draws bounding boxes of server entities
6823 for (i = 0;i < prog->num_edicts;i++)
6825 edict = PRVM_EDICT_NUM(i);
6826 if (edict->priv.server->free)
6828 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6829 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6831 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6833 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6834 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6840 static const int nomodelelement3i[24] =
6852 static const unsigned short nomodelelement3s[24] =
6864 static const float nomodelvertex3f[6*3] =
6874 static const float nomodelcolor4f[6*4] =
6876 0.0f, 0.0f, 0.5f, 1.0f,
6877 0.0f, 0.0f, 0.5f, 1.0f,
6878 0.0f, 0.5f, 0.0f, 1.0f,
6879 0.0f, 0.5f, 0.0f, 1.0f,
6880 0.5f, 0.0f, 0.0f, 1.0f,
6881 0.5f, 0.0f, 0.0f, 1.0f
6884 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6890 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);
6892 // this is only called once per entity so numsurfaces is always 1, and
6893 // surfacelist is always {0}, so this code does not handle batches
6895 if (rsurface.ent_flags & RENDER_ADDITIVE)
6897 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6898 GL_DepthMask(false);
6900 else if (rsurface.colormod[3] < 1)
6902 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6903 GL_DepthMask(false);
6907 GL_BlendFunc(GL_ONE, GL_ZERO);
6910 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6911 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6912 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6913 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6914 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6915 for (i = 0, c = color4f;i < 6;i++, c += 4)
6917 c[0] *= rsurface.colormod[0];
6918 c[1] *= rsurface.colormod[1];
6919 c[2] *= rsurface.colormod[2];
6920 c[3] *= rsurface.colormod[3];
6922 if (r_refdef.fogenabled)
6924 for (i = 0, c = color4f;i < 6;i++, c += 4)
6926 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6928 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6929 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6930 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6933 // R_Mesh_ResetTextureState();
6934 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6935 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6936 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6939 void R_DrawNoModel(entity_render_t *ent)
6942 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6943 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6944 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6946 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6949 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6951 vec3_t right1, right2, diff, normal;
6953 VectorSubtract (org2, org1, normal);
6955 // calculate 'right' vector for start
6956 VectorSubtract (r_refdef.view.origin, org1, diff);
6957 CrossProduct (normal, diff, right1);
6958 VectorNormalize (right1);
6960 // calculate 'right' vector for end
6961 VectorSubtract (r_refdef.view.origin, org2, diff);
6962 CrossProduct (normal, diff, right2);
6963 VectorNormalize (right2);
6965 vert[ 0] = org1[0] + width * right1[0];
6966 vert[ 1] = org1[1] + width * right1[1];
6967 vert[ 2] = org1[2] + width * right1[2];
6968 vert[ 3] = org1[0] - width * right1[0];
6969 vert[ 4] = org1[1] - width * right1[1];
6970 vert[ 5] = org1[2] - width * right1[2];
6971 vert[ 6] = org2[0] - width * right2[0];
6972 vert[ 7] = org2[1] - width * right2[1];
6973 vert[ 8] = org2[2] - width * right2[2];
6974 vert[ 9] = org2[0] + width * right2[0];
6975 vert[10] = org2[1] + width * right2[1];
6976 vert[11] = org2[2] + width * right2[2];
6979 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)
6981 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6982 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6983 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6984 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6985 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
6986 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
6987 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
6988 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
6989 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
6990 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
6991 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
6992 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
6995 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7000 VectorSet(v, x, y, z);
7001 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7002 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7004 if (i == mesh->numvertices)
7006 if (mesh->numvertices < mesh->maxvertices)
7008 VectorCopy(v, vertex3f);
7009 mesh->numvertices++;
7011 return mesh->numvertices;
7017 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7021 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7022 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7023 e = mesh->element3i + mesh->numtriangles * 3;
7024 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7026 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7027 if (mesh->numtriangles < mesh->maxtriangles)
7032 mesh->numtriangles++;
7034 element[1] = element[2];
7038 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7042 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7043 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7044 e = mesh->element3i + mesh->numtriangles * 3;
7045 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7047 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7048 if (mesh->numtriangles < mesh->maxtriangles)
7053 mesh->numtriangles++;
7055 element[1] = element[2];
7059 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7060 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7062 int planenum, planenum2;
7065 mplane_t *plane, *plane2;
7067 double temppoints[2][256*3];
7068 // figure out how large a bounding box we need to properly compute this brush
7070 for (w = 0;w < numplanes;w++)
7071 maxdist = max(maxdist, fabs(planes[w].dist));
7072 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7073 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7074 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7078 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7079 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7081 if (planenum2 == planenum)
7083 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);
7086 if (tempnumpoints < 3)
7088 // generate elements forming a triangle fan for this polygon
7089 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7093 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)
7095 texturelayer_t *layer;
7096 layer = t->currentlayers + t->currentnumlayers++;
7098 layer->depthmask = depthmask;
7099 layer->blendfunc1 = blendfunc1;
7100 layer->blendfunc2 = blendfunc2;
7101 layer->texture = texture;
7102 layer->texmatrix = *matrix;
7103 layer->color[0] = r;
7104 layer->color[1] = g;
7105 layer->color[2] = b;
7106 layer->color[3] = a;
7109 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7111 if(parms[0] == 0 && parms[1] == 0)
7113 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7114 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7119 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7122 index = parms[2] + r_refdef.scene.time * parms[3];
7123 index -= floor(index);
7124 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7127 case Q3WAVEFUNC_NONE:
7128 case Q3WAVEFUNC_NOISE:
7129 case Q3WAVEFUNC_COUNT:
7132 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7133 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7134 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7135 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7136 case Q3WAVEFUNC_TRIANGLE:
7138 f = index - floor(index);
7149 f = parms[0] + parms[1] * f;
7150 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7151 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7155 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7160 matrix4x4_t matrix, temp;
7161 switch(tcmod->tcmod)
7165 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7166 matrix = r_waterscrollmatrix;
7168 matrix = identitymatrix;
7170 case Q3TCMOD_ENTITYTRANSLATE:
7171 // this is used in Q3 to allow the gamecode to control texcoord
7172 // scrolling on the entity, which is not supported in darkplaces yet.
7173 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7175 case Q3TCMOD_ROTATE:
7176 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7177 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7178 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7181 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7183 case Q3TCMOD_SCROLL:
7184 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7186 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7187 w = (int) tcmod->parms[0];
7188 h = (int) tcmod->parms[1];
7189 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7191 idx = (int) floor(f * w * h);
7192 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7194 case Q3TCMOD_STRETCH:
7195 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7196 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7198 case Q3TCMOD_TRANSFORM:
7199 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7200 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7201 VectorSet(tcmat + 6, 0 , 0 , 1);
7202 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7203 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7205 case Q3TCMOD_TURBULENT:
7206 // this is handled in the RSurf_PrepareVertices function
7207 matrix = identitymatrix;
7211 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7214 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7216 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7217 char name[MAX_QPATH];
7218 skinframe_t *skinframe;
7219 unsigned char pixels[296*194];
7220 strlcpy(cache->name, skinname, sizeof(cache->name));
7221 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7222 if (developer_loading.integer)
7223 Con_Printf("loading %s\n", name);
7224 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7225 if (!skinframe || !skinframe->base)
7228 fs_offset_t filesize;
7230 f = FS_LoadFile(name, tempmempool, true, &filesize);
7233 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7234 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7238 cache->skinframe = skinframe;
7241 texture_t *R_GetCurrentTexture(texture_t *t)
7244 const entity_render_t *ent = rsurface.entity;
7245 dp_model_t *model = ent->model;
7246 q3shaderinfo_layer_tcmod_t *tcmod;
7248 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7249 return t->currentframe;
7250 t->update_lastrenderframe = r_textureframe;
7251 t->update_lastrenderentity = (void *)ent;
7253 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7254 t->camera_entity = ent->entitynumber;
7256 t->camera_entity = 0;
7258 // switch to an alternate material if this is a q1bsp animated material
7260 texture_t *texture = t;
7261 int s = rsurface.ent_skinnum;
7262 if ((unsigned int)s >= (unsigned int)model->numskins)
7264 if (model->skinscenes)
7266 if (model->skinscenes[s].framecount > 1)
7267 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7269 s = model->skinscenes[s].firstframe;
7272 t = t + s * model->num_surfaces;
7275 // use an alternate animation if the entity's frame is not 0,
7276 // and only if the texture has an alternate animation
7277 if (rsurface.ent_alttextures && t->anim_total[1])
7278 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7280 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7282 texture->currentframe = t;
7285 // update currentskinframe to be a qw skin or animation frame
7286 if (rsurface.ent_qwskin >= 0)
7288 i = rsurface.ent_qwskin;
7289 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7291 r_qwskincache_size = cl.maxclients;
7293 Mem_Free(r_qwskincache);
7294 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7296 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7297 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7298 t->currentskinframe = r_qwskincache[i].skinframe;
7299 if (t->currentskinframe == NULL)
7300 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7302 else if (t->numskinframes >= 2)
7303 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7304 if (t->backgroundnumskinframes >= 2)
7305 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7307 t->currentmaterialflags = t->basematerialflags;
7308 t->currentalpha = rsurface.colormod[3];
7309 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7310 t->currentalpha *= r_wateralpha.value;
7311 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7312 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7313 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7314 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7315 if (!(rsurface.ent_flags & RENDER_LIGHT))
7316 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7317 else if (FAKELIGHT_ENABLED)
7319 // no modellight if using fakelight for the map
7321 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7323 // pick a model lighting mode
7324 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7325 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7327 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7329 if (rsurface.ent_flags & RENDER_ADDITIVE)
7330 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7331 else if (t->currentalpha < 1)
7332 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7333 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7334 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7335 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7336 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7337 if (t->backgroundnumskinframes)
7338 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7339 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7341 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7342 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7345 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7346 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7347 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7349 // there is no tcmod
7350 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7352 t->currenttexmatrix = r_waterscrollmatrix;
7353 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7355 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7357 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7358 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7361 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7362 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7363 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7364 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7366 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7367 if (t->currentskinframe->qpixels)
7368 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7369 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7370 if (!t->basetexture)
7371 t->basetexture = r_texture_notexture;
7372 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7373 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7374 t->nmaptexture = t->currentskinframe->nmap;
7375 if (!t->nmaptexture)
7376 t->nmaptexture = r_texture_blanknormalmap;
7377 t->glosstexture = r_texture_black;
7378 t->glowtexture = t->currentskinframe->glow;
7379 t->fogtexture = t->currentskinframe->fog;
7380 t->reflectmasktexture = t->currentskinframe->reflect;
7381 if (t->backgroundnumskinframes)
7383 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7384 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7385 t->backgroundglosstexture = r_texture_black;
7386 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7387 if (!t->backgroundnmaptexture)
7388 t->backgroundnmaptexture = r_texture_blanknormalmap;
7392 t->backgroundbasetexture = r_texture_white;
7393 t->backgroundnmaptexture = r_texture_blanknormalmap;
7394 t->backgroundglosstexture = r_texture_black;
7395 t->backgroundglowtexture = NULL;
7397 t->specularpower = r_shadow_glossexponent.value;
7398 // TODO: store reference values for these in the texture?
7399 t->specularscale = 0;
7400 if (r_shadow_gloss.integer > 0)
7402 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7404 if (r_shadow_glossintensity.value > 0)
7406 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7407 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7408 t->specularscale = r_shadow_glossintensity.value;
7411 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7413 t->glosstexture = r_texture_white;
7414 t->backgroundglosstexture = r_texture_white;
7415 t->specularscale = r_shadow_gloss2intensity.value;
7416 t->specularpower = r_shadow_gloss2exponent.value;
7419 t->specularscale *= t->specularscalemod;
7420 t->specularpower *= t->specularpowermod;
7422 // lightmaps mode looks bad with dlights using actual texturing, so turn
7423 // off the colormap and glossmap, but leave the normalmap on as it still
7424 // accurately represents the shading involved
7425 if (gl_lightmaps.integer)
7427 t->basetexture = r_texture_grey128;
7428 t->pantstexture = r_texture_black;
7429 t->shirttexture = r_texture_black;
7430 t->nmaptexture = r_texture_blanknormalmap;
7431 t->glosstexture = r_texture_black;
7432 t->glowtexture = NULL;
7433 t->fogtexture = NULL;
7434 t->reflectmasktexture = NULL;
7435 t->backgroundbasetexture = NULL;
7436 t->backgroundnmaptexture = r_texture_blanknormalmap;
7437 t->backgroundglosstexture = r_texture_black;
7438 t->backgroundglowtexture = NULL;
7439 t->specularscale = 0;
7440 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7443 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7444 VectorClear(t->dlightcolor);
7445 t->currentnumlayers = 0;
7446 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7448 int blendfunc1, blendfunc2;
7450 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7452 blendfunc1 = GL_SRC_ALPHA;
7453 blendfunc2 = GL_ONE;
7455 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7457 blendfunc1 = GL_SRC_ALPHA;
7458 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7460 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7462 blendfunc1 = t->customblendfunc[0];
7463 blendfunc2 = t->customblendfunc[1];
7467 blendfunc1 = GL_ONE;
7468 blendfunc2 = GL_ZERO;
7470 // don't colormod evilblend textures
7471 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7472 VectorSet(t->lightmapcolor, 1, 1, 1);
7473 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7474 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7476 // fullbright is not affected by r_refdef.lightmapintensity
7477 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]);
7478 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7479 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]);
7480 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7481 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]);
7485 vec3_t ambientcolor;
7487 // set the color tint used for lights affecting this surface
7488 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7490 // q3bsp has no lightmap updates, so the lightstylevalue that
7491 // would normally be baked into the lightmap must be
7492 // applied to the color
7493 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7494 if (model->type == mod_brushq3)
7495 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7496 colorscale *= r_refdef.lightmapintensity;
7497 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7498 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7499 // basic lit geometry
7500 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]);
7501 // add pants/shirt if needed
7502 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7503 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]);
7504 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7505 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]);
7506 // now add ambient passes if needed
7507 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7509 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]);
7510 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7511 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]);
7512 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7513 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]);
7516 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7517 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]);
7518 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7520 // if this is opaque use alpha blend which will darken the earlier
7523 // if this is an alpha blended material, all the earlier passes
7524 // were darkened by fog already, so we only need to add the fog
7525 // color ontop through the fog mask texture
7527 // if this is an additive blended material, all the earlier passes
7528 // were darkened by fog already, and we should not add fog color
7529 // (because the background was not darkened, there is no fog color
7530 // that was lost behind it).
7531 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]);
7535 return t->currentframe;
7538 rsurfacestate_t rsurface;
7540 void RSurf_ActiveWorldEntity(void)
7542 dp_model_t *model = r_refdef.scene.worldmodel;
7543 //if (rsurface.entity == r_refdef.scene.worldentity)
7545 rsurface.entity = r_refdef.scene.worldentity;
7546 rsurface.skeleton = NULL;
7547 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7548 rsurface.ent_skinnum = 0;
7549 rsurface.ent_qwskin = -1;
7550 rsurface.ent_shadertime = 0;
7551 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7552 rsurface.matrix = identitymatrix;
7553 rsurface.inversematrix = identitymatrix;
7554 rsurface.matrixscale = 1;
7555 rsurface.inversematrixscale = 1;
7556 R_EntityMatrix(&identitymatrix);
7557 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7558 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7559 rsurface.fograngerecip = r_refdef.fograngerecip;
7560 rsurface.fogheightfade = r_refdef.fogheightfade;
7561 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7562 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7563 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7564 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7565 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7566 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7567 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7568 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7569 rsurface.colormod[3] = 1;
7570 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);
7571 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7572 rsurface.frameblend[0].lerp = 1;
7573 rsurface.ent_alttextures = false;
7574 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7575 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7576 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7577 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7578 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7579 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7580 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7581 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7582 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7583 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7584 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7585 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7586 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7587 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7588 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7589 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7590 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7591 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7592 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7593 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7594 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7595 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7596 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7597 rsurface.modelelement3i = model->surfmesh.data_element3i;
7598 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7599 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7600 rsurface.modelelement3s = model->surfmesh.data_element3s;
7601 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7602 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7603 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7604 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7605 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7606 rsurface.modelsurfaces = model->data_surfaces;
7607 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7608 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7609 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7610 rsurface.modelgeneratedvertex = false;
7611 rsurface.batchgeneratedvertex = false;
7612 rsurface.batchfirstvertex = 0;
7613 rsurface.batchnumvertices = 0;
7614 rsurface.batchfirsttriangle = 0;
7615 rsurface.batchnumtriangles = 0;
7616 rsurface.batchvertex3f = NULL;
7617 rsurface.batchvertex3f_vertexbuffer = NULL;
7618 rsurface.batchvertex3f_bufferoffset = 0;
7619 rsurface.batchsvector3f = NULL;
7620 rsurface.batchsvector3f_vertexbuffer = NULL;
7621 rsurface.batchsvector3f_bufferoffset = 0;
7622 rsurface.batchtvector3f = NULL;
7623 rsurface.batchtvector3f_vertexbuffer = NULL;
7624 rsurface.batchtvector3f_bufferoffset = 0;
7625 rsurface.batchnormal3f = NULL;
7626 rsurface.batchnormal3f_vertexbuffer = NULL;
7627 rsurface.batchnormal3f_bufferoffset = 0;
7628 rsurface.batchlightmapcolor4f = NULL;
7629 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7630 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7631 rsurface.batchtexcoordtexture2f = NULL;
7632 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7633 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7634 rsurface.batchtexcoordlightmap2f = NULL;
7635 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7636 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7637 rsurface.batchvertexmesh = NULL;
7638 rsurface.batchvertexmeshbuffer = NULL;
7639 rsurface.batchvertex3fbuffer = NULL;
7640 rsurface.batchelement3i = NULL;
7641 rsurface.batchelement3i_indexbuffer = NULL;
7642 rsurface.batchelement3i_bufferoffset = 0;
7643 rsurface.batchelement3s = NULL;
7644 rsurface.batchelement3s_indexbuffer = NULL;
7645 rsurface.batchelement3s_bufferoffset = 0;
7646 rsurface.passcolor4f = NULL;
7647 rsurface.passcolor4f_vertexbuffer = NULL;
7648 rsurface.passcolor4f_bufferoffset = 0;
7651 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7653 dp_model_t *model = ent->model;
7654 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7656 rsurface.entity = (entity_render_t *)ent;
7657 rsurface.skeleton = ent->skeleton;
7658 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7659 rsurface.ent_skinnum = ent->skinnum;
7660 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;
7661 rsurface.ent_shadertime = ent->shadertime;
7662 rsurface.ent_flags = ent->flags;
7663 rsurface.matrix = ent->matrix;
7664 rsurface.inversematrix = ent->inversematrix;
7665 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7666 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7667 R_EntityMatrix(&rsurface.matrix);
7668 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7669 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7670 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7671 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7672 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7673 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7674 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7675 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7676 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7677 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7678 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7679 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7680 rsurface.colormod[3] = ent->alpha;
7681 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7682 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7683 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7684 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7685 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7686 if (ent->model->brush.submodel && !prepass)
7688 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7689 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7691 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7693 if (ent->animcache_vertex3f)
7695 rsurface.modelvertex3f = ent->animcache_vertex3f;
7696 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7697 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7698 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7699 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7700 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7701 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7703 else if (wanttangents)
7705 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7706 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7707 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7708 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7709 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7710 rsurface.modelvertexmesh = NULL;
7711 rsurface.modelvertexmeshbuffer = NULL;
7712 rsurface.modelvertex3fbuffer = NULL;
7714 else if (wantnormals)
7716 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7717 rsurface.modelsvector3f = NULL;
7718 rsurface.modeltvector3f = NULL;
7719 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7720 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7721 rsurface.modelvertexmesh = NULL;
7722 rsurface.modelvertexmeshbuffer = NULL;
7723 rsurface.modelvertex3fbuffer = NULL;
7727 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7728 rsurface.modelsvector3f = NULL;
7729 rsurface.modeltvector3f = NULL;
7730 rsurface.modelnormal3f = NULL;
7731 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7732 rsurface.modelvertexmesh = NULL;
7733 rsurface.modelvertexmeshbuffer = NULL;
7734 rsurface.modelvertex3fbuffer = NULL;
7736 rsurface.modelvertex3f_vertexbuffer = 0;
7737 rsurface.modelvertex3f_bufferoffset = 0;
7738 rsurface.modelsvector3f_vertexbuffer = 0;
7739 rsurface.modelsvector3f_bufferoffset = 0;
7740 rsurface.modeltvector3f_vertexbuffer = 0;
7741 rsurface.modeltvector3f_bufferoffset = 0;
7742 rsurface.modelnormal3f_vertexbuffer = 0;
7743 rsurface.modelnormal3f_bufferoffset = 0;
7744 rsurface.modelgeneratedvertex = true;
7748 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7749 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7750 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7751 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7752 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7753 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7754 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7755 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7756 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7757 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7758 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7759 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7760 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7761 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7762 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7763 rsurface.modelgeneratedvertex = false;
7765 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7766 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7767 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7768 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7769 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7770 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7771 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7772 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7773 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7774 rsurface.modelelement3i = model->surfmesh.data_element3i;
7775 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7776 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7777 rsurface.modelelement3s = model->surfmesh.data_element3s;
7778 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7779 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7780 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7781 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7782 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7783 rsurface.modelsurfaces = model->data_surfaces;
7784 rsurface.batchgeneratedvertex = false;
7785 rsurface.batchfirstvertex = 0;
7786 rsurface.batchnumvertices = 0;
7787 rsurface.batchfirsttriangle = 0;
7788 rsurface.batchnumtriangles = 0;
7789 rsurface.batchvertex3f = NULL;
7790 rsurface.batchvertex3f_vertexbuffer = NULL;
7791 rsurface.batchvertex3f_bufferoffset = 0;
7792 rsurface.batchsvector3f = NULL;
7793 rsurface.batchsvector3f_vertexbuffer = NULL;
7794 rsurface.batchsvector3f_bufferoffset = 0;
7795 rsurface.batchtvector3f = NULL;
7796 rsurface.batchtvector3f_vertexbuffer = NULL;
7797 rsurface.batchtvector3f_bufferoffset = 0;
7798 rsurface.batchnormal3f = NULL;
7799 rsurface.batchnormal3f_vertexbuffer = NULL;
7800 rsurface.batchnormal3f_bufferoffset = 0;
7801 rsurface.batchlightmapcolor4f = NULL;
7802 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7803 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7804 rsurface.batchtexcoordtexture2f = NULL;
7805 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7806 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7807 rsurface.batchtexcoordlightmap2f = NULL;
7808 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7809 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7810 rsurface.batchvertexmesh = NULL;
7811 rsurface.batchvertexmeshbuffer = NULL;
7812 rsurface.batchvertex3fbuffer = NULL;
7813 rsurface.batchelement3i = NULL;
7814 rsurface.batchelement3i_indexbuffer = NULL;
7815 rsurface.batchelement3i_bufferoffset = 0;
7816 rsurface.batchelement3s = NULL;
7817 rsurface.batchelement3s_indexbuffer = NULL;
7818 rsurface.batchelement3s_bufferoffset = 0;
7819 rsurface.passcolor4f = NULL;
7820 rsurface.passcolor4f_vertexbuffer = NULL;
7821 rsurface.passcolor4f_bufferoffset = 0;
7824 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)
7826 rsurface.entity = r_refdef.scene.worldentity;
7827 rsurface.skeleton = NULL;
7828 rsurface.ent_skinnum = 0;
7829 rsurface.ent_qwskin = -1;
7830 rsurface.ent_shadertime = shadertime;
7831 rsurface.ent_flags = entflags;
7832 rsurface.modelnumvertices = numvertices;
7833 rsurface.modelnumtriangles = numtriangles;
7834 rsurface.matrix = *matrix;
7835 rsurface.inversematrix = *inversematrix;
7836 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7837 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7838 R_EntityMatrix(&rsurface.matrix);
7839 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7840 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7841 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7842 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7843 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7844 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7845 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7846 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7847 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7848 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7849 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7850 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7851 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);
7852 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7853 rsurface.frameblend[0].lerp = 1;
7854 rsurface.ent_alttextures = false;
7855 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7856 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7859 rsurface.modelvertex3f = (float *)vertex3f;
7860 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7861 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7862 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7864 else if (wantnormals)
7866 rsurface.modelvertex3f = (float *)vertex3f;
7867 rsurface.modelsvector3f = NULL;
7868 rsurface.modeltvector3f = NULL;
7869 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7873 rsurface.modelvertex3f = (float *)vertex3f;
7874 rsurface.modelsvector3f = NULL;
7875 rsurface.modeltvector3f = NULL;
7876 rsurface.modelnormal3f = NULL;
7878 rsurface.modelvertexmesh = NULL;
7879 rsurface.modelvertexmeshbuffer = NULL;
7880 rsurface.modelvertex3fbuffer = NULL;
7881 rsurface.modelvertex3f_vertexbuffer = 0;
7882 rsurface.modelvertex3f_bufferoffset = 0;
7883 rsurface.modelsvector3f_vertexbuffer = 0;
7884 rsurface.modelsvector3f_bufferoffset = 0;
7885 rsurface.modeltvector3f_vertexbuffer = 0;
7886 rsurface.modeltvector3f_bufferoffset = 0;
7887 rsurface.modelnormal3f_vertexbuffer = 0;
7888 rsurface.modelnormal3f_bufferoffset = 0;
7889 rsurface.modelgeneratedvertex = true;
7890 rsurface.modellightmapcolor4f = (float *)color4f;
7891 rsurface.modellightmapcolor4f_vertexbuffer = 0;
7892 rsurface.modellightmapcolor4f_bufferoffset = 0;
7893 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
7894 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7895 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7896 rsurface.modeltexcoordlightmap2f = NULL;
7897 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7898 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7899 rsurface.modelelement3i = (int *)element3i;
7900 rsurface.modelelement3i_indexbuffer = NULL;
7901 rsurface.modelelement3i_bufferoffset = 0;
7902 rsurface.modelelement3s = (unsigned short *)element3s;
7903 rsurface.modelelement3s_indexbuffer = NULL;
7904 rsurface.modelelement3s_bufferoffset = 0;
7905 rsurface.modellightmapoffsets = NULL;
7906 rsurface.modelsurfaces = NULL;
7907 rsurface.batchgeneratedvertex = false;
7908 rsurface.batchfirstvertex = 0;
7909 rsurface.batchnumvertices = 0;
7910 rsurface.batchfirsttriangle = 0;
7911 rsurface.batchnumtriangles = 0;
7912 rsurface.batchvertex3f = NULL;
7913 rsurface.batchvertex3f_vertexbuffer = NULL;
7914 rsurface.batchvertex3f_bufferoffset = 0;
7915 rsurface.batchsvector3f = NULL;
7916 rsurface.batchsvector3f_vertexbuffer = NULL;
7917 rsurface.batchsvector3f_bufferoffset = 0;
7918 rsurface.batchtvector3f = NULL;
7919 rsurface.batchtvector3f_vertexbuffer = NULL;
7920 rsurface.batchtvector3f_bufferoffset = 0;
7921 rsurface.batchnormal3f = NULL;
7922 rsurface.batchnormal3f_vertexbuffer = NULL;
7923 rsurface.batchnormal3f_bufferoffset = 0;
7924 rsurface.batchlightmapcolor4f = NULL;
7925 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7926 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7927 rsurface.batchtexcoordtexture2f = NULL;
7928 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7929 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7930 rsurface.batchtexcoordlightmap2f = NULL;
7931 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7932 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7933 rsurface.batchvertexmesh = NULL;
7934 rsurface.batchvertexmeshbuffer = NULL;
7935 rsurface.batchvertex3fbuffer = NULL;
7936 rsurface.batchelement3i = NULL;
7937 rsurface.batchelement3i_indexbuffer = NULL;
7938 rsurface.batchelement3i_bufferoffset = 0;
7939 rsurface.batchelement3s = NULL;
7940 rsurface.batchelement3s_indexbuffer = NULL;
7941 rsurface.batchelement3s_bufferoffset = 0;
7942 rsurface.passcolor4f = NULL;
7943 rsurface.passcolor4f_vertexbuffer = NULL;
7944 rsurface.passcolor4f_bufferoffset = 0;
7946 if (rsurface.modelnumvertices && rsurface.modelelement3i)
7948 if ((wantnormals || wanttangents) && !normal3f)
7950 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7951 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7953 if (wanttangents && !svector3f)
7955 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7956 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7957 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7962 float RSurf_FogPoint(const float *v)
7964 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7965 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7966 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7967 float FogHeightFade = r_refdef.fogheightfade;
7969 unsigned int fogmasktableindex;
7970 if (r_refdef.fogplaneviewabove)
7971 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7973 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7974 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7975 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7978 float RSurf_FogVertex(const float *v)
7980 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7981 float FogPlaneViewDist = rsurface.fogplaneviewdist;
7982 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7983 float FogHeightFade = rsurface.fogheightfade;
7985 unsigned int fogmasktableindex;
7986 if (r_refdef.fogplaneviewabove)
7987 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7989 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7990 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
7991 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7994 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
7997 for (i = 0;i < numelements;i++)
7998 outelement3i[i] = inelement3i[i] + adjust;
8001 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8002 extern cvar_t gl_vbo;
8003 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8011 int surfacefirsttriangle;
8012 int surfacenumtriangles;
8013 int surfacefirstvertex;
8014 int surfaceendvertex;
8015 int surfacenumvertices;
8016 int batchnumvertices;
8017 int batchnumtriangles;
8021 qboolean dynamicvertex;
8025 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8027 q3shaderinfo_deform_t *deform;
8028 const msurface_t *surface, *firstsurface;
8029 r_vertexmesh_t *vertexmesh;
8030 if (!texturenumsurfaces)
8032 // find vertex range of this surface batch
8034 firstsurface = texturesurfacelist[0];
8035 firsttriangle = firstsurface->num_firsttriangle;
8036 batchnumvertices = 0;
8037 batchnumtriangles = 0;
8038 firstvertex = endvertex = firstsurface->num_firstvertex;
8039 for (i = 0;i < texturenumsurfaces;i++)
8041 surface = texturesurfacelist[i];
8042 if (surface != firstsurface + i)
8044 surfacefirstvertex = surface->num_firstvertex;
8045 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8046 surfacenumvertices = surface->num_vertices;
8047 surfacenumtriangles = surface->num_triangles;
8048 if (firstvertex > surfacefirstvertex)
8049 firstvertex = surfacefirstvertex;
8050 if (endvertex < surfaceendvertex)
8051 endvertex = surfaceendvertex;
8052 batchnumvertices += surfacenumvertices;
8053 batchnumtriangles += surfacenumtriangles;
8056 // we now know the vertex range used, and if there are any gaps in it
8057 rsurface.batchfirstvertex = firstvertex;
8058 rsurface.batchnumvertices = endvertex - firstvertex;
8059 rsurface.batchfirsttriangle = firsttriangle;
8060 rsurface.batchnumtriangles = batchnumtriangles;
8062 // this variable holds flags for which properties have been updated that
8063 // may require regenerating vertexmesh array...
8066 // check if any dynamic vertex processing must occur
8067 dynamicvertex = false;
8069 // if there is a chance of animated vertex colors, it's a dynamic batch
8070 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8072 dynamicvertex = true;
8073 batchneed |= BATCHNEED_NOGAPS;
8074 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8077 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8079 switch (deform->deform)
8082 case Q3DEFORM_PROJECTIONSHADOW:
8083 case Q3DEFORM_TEXT0:
8084 case Q3DEFORM_TEXT1:
8085 case Q3DEFORM_TEXT2:
8086 case Q3DEFORM_TEXT3:
8087 case Q3DEFORM_TEXT4:
8088 case Q3DEFORM_TEXT5:
8089 case Q3DEFORM_TEXT6:
8090 case Q3DEFORM_TEXT7:
8093 case Q3DEFORM_AUTOSPRITE:
8094 dynamicvertex = true;
8095 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8096 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8098 case Q3DEFORM_AUTOSPRITE2:
8099 dynamicvertex = true;
8100 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8101 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8103 case Q3DEFORM_NORMAL:
8104 dynamicvertex = true;
8105 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8106 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8109 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8110 break; // if wavefunc is a nop, ignore this transform
8111 dynamicvertex = true;
8112 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8113 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8115 case Q3DEFORM_BULGE:
8116 dynamicvertex = true;
8117 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8118 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8121 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8122 break; // if wavefunc is a nop, ignore this transform
8123 dynamicvertex = true;
8124 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8125 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8129 switch(rsurface.texture->tcgen.tcgen)
8132 case Q3TCGEN_TEXTURE:
8134 case Q3TCGEN_LIGHTMAP:
8135 dynamicvertex = true;
8136 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8137 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8139 case Q3TCGEN_VECTOR:
8140 dynamicvertex = true;
8141 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8142 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8144 case Q3TCGEN_ENVIRONMENT:
8145 dynamicvertex = true;
8146 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8147 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8150 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8152 dynamicvertex = true;
8153 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8154 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8157 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8159 dynamicvertex = true;
8160 batchneed |= BATCHNEED_NOGAPS;
8161 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8164 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8166 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8167 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8168 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8169 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8170 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8171 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8172 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8175 // when the model data has no vertex buffer (dynamic mesh), we need to
8177 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8178 batchneed |= BATCHNEED_NOGAPS;
8180 // if needsupdate, we have to do a dynamic vertex batch for sure
8181 if (needsupdate & batchneed)
8182 dynamicvertex = true;
8184 // see if we need to build vertexmesh from arrays
8185 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8186 dynamicvertex = true;
8188 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8189 // also some drivers strongly dislike firstvertex
8190 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8191 dynamicvertex = true;
8193 rsurface.batchvertex3f = rsurface.modelvertex3f;
8194 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8195 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8196 rsurface.batchsvector3f = rsurface.modelsvector3f;
8197 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8198 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8199 rsurface.batchtvector3f = rsurface.modeltvector3f;
8200 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8201 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8202 rsurface.batchnormal3f = rsurface.modelnormal3f;
8203 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8204 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8205 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8206 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8207 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8208 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8209 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8210 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8211 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8212 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8213 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8214 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8215 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8216 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8217 rsurface.batchelement3i = rsurface.modelelement3i;
8218 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8219 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8220 rsurface.batchelement3s = rsurface.modelelement3s;
8221 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8222 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8224 // if any dynamic vertex processing has to occur in software, we copy the
8225 // entire surface list together before processing to rebase the vertices
8226 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8228 // if any gaps exist and we do not have a static vertex buffer, we have to
8229 // copy the surface list together to avoid wasting upload bandwidth on the
8230 // vertices in the gaps.
8232 // if gaps exist and we have a static vertex buffer, we still have to
8233 // combine the index buffer ranges into one dynamic index buffer.
8235 // in all cases we end up with data that can be drawn in one call.
8239 // static vertex data, just set pointers...
8240 rsurface.batchgeneratedvertex = false;
8241 // if there are gaps, we want to build a combined index buffer,
8242 // otherwise use the original static buffer with an appropriate offset
8245 // build a new triangle elements array for this batch
8246 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8247 rsurface.batchfirsttriangle = 0;
8249 for (i = 0;i < texturenumsurfaces;i++)
8251 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8252 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8253 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8254 numtriangles += surfacenumtriangles;
8256 rsurface.batchelement3i_indexbuffer = NULL;
8257 rsurface.batchelement3i_bufferoffset = 0;
8258 rsurface.batchelement3s = NULL;
8259 rsurface.batchelement3s_indexbuffer = NULL;
8260 rsurface.batchelement3s_bufferoffset = 0;
8261 if (endvertex <= 65536)
8263 // make a 16bit (unsigned short) index array if possible
8264 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8265 for (i = 0;i < numtriangles*3;i++)
8266 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8272 // something needs software processing, do it for real...
8273 // we only directly handle separate array data in this case and then
8274 // generate interleaved data if needed...
8275 rsurface.batchgeneratedvertex = true;
8277 // now copy the vertex data into a combined array and make an index array
8278 // (this is what Quake3 does all the time)
8279 //if (gaps || rsurface.batchfirstvertex)
8281 rsurface.batchvertex3fbuffer = NULL;
8282 rsurface.batchvertexmesh = NULL;
8283 rsurface.batchvertexmeshbuffer = NULL;
8284 rsurface.batchvertex3f = NULL;
8285 rsurface.batchvertex3f_vertexbuffer = NULL;
8286 rsurface.batchvertex3f_bufferoffset = 0;
8287 rsurface.batchsvector3f = NULL;
8288 rsurface.batchsvector3f_vertexbuffer = NULL;
8289 rsurface.batchsvector3f_bufferoffset = 0;
8290 rsurface.batchtvector3f = NULL;
8291 rsurface.batchtvector3f_vertexbuffer = NULL;
8292 rsurface.batchtvector3f_bufferoffset = 0;
8293 rsurface.batchnormal3f = NULL;
8294 rsurface.batchnormal3f_vertexbuffer = NULL;
8295 rsurface.batchnormal3f_bufferoffset = 0;
8296 rsurface.batchlightmapcolor4f = NULL;
8297 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8298 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8299 rsurface.batchtexcoordtexture2f = NULL;
8300 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8301 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8302 rsurface.batchtexcoordlightmap2f = NULL;
8303 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8304 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8305 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8306 rsurface.batchelement3i_indexbuffer = NULL;
8307 rsurface.batchelement3i_bufferoffset = 0;
8308 rsurface.batchelement3s = NULL;
8309 rsurface.batchelement3s_indexbuffer = NULL;
8310 rsurface.batchelement3s_bufferoffset = 0;
8311 // we'll only be setting up certain arrays as needed
8312 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8313 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8314 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8315 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8316 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8317 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8318 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8320 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8321 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8323 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8324 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8325 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8326 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8327 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8328 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8331 for (i = 0;i < texturenumsurfaces;i++)
8333 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8334 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8335 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8336 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8337 // copy only the data requested
8338 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8339 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8340 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8342 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8343 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8344 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8345 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8346 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8348 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8349 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8351 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8352 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8353 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8354 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8355 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8356 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8358 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8359 numvertices += surfacenumvertices;
8360 numtriangles += surfacenumtriangles;
8363 // generate a 16bit index array as well if possible
8364 // (in general, dynamic batches fit)
8365 if (numvertices <= 65536)
8367 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8368 for (i = 0;i < numtriangles*3;i++)
8369 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8372 // since we've copied everything, the batch now starts at 0
8373 rsurface.batchfirstvertex = 0;
8374 rsurface.batchnumvertices = batchnumvertices;
8375 rsurface.batchfirsttriangle = 0;
8376 rsurface.batchnumtriangles = batchnumtriangles;
8379 // q1bsp surfaces rendered in vertex color mode have to have colors
8380 // calculated based on lightstyles
8381 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8383 // generate color arrays for the surfaces in this list
8388 const unsigned char *lm;
8389 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8390 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8391 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8393 for (i = 0;i < texturenumsurfaces;i++)
8395 surface = texturesurfacelist[i];
8396 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8397 surfacenumvertices = surface->num_vertices;
8398 if (surface->lightmapinfo->samples)
8400 for (j = 0;j < surfacenumvertices;j++)
8402 lm = surface->lightmapinfo->samples + offsets[j];
8403 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8404 VectorScale(lm, scale, c);
8405 if (surface->lightmapinfo->styles[1] != 255)
8407 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8409 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8410 VectorMA(c, scale, lm, c);
8411 if (surface->lightmapinfo->styles[2] != 255)
8414 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8415 VectorMA(c, scale, lm, c);
8416 if (surface->lightmapinfo->styles[3] != 255)
8419 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8420 VectorMA(c, scale, lm, c);
8427 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);
8433 for (j = 0;j < surfacenumvertices;j++)
8435 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8442 // if vertices are deformed (sprite flares and things in maps, possibly
8443 // water waves, bulges and other deformations), modify the copied vertices
8445 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8447 switch (deform->deform)
8450 case Q3DEFORM_PROJECTIONSHADOW:
8451 case Q3DEFORM_TEXT0:
8452 case Q3DEFORM_TEXT1:
8453 case Q3DEFORM_TEXT2:
8454 case Q3DEFORM_TEXT3:
8455 case Q3DEFORM_TEXT4:
8456 case Q3DEFORM_TEXT5:
8457 case Q3DEFORM_TEXT6:
8458 case Q3DEFORM_TEXT7:
8461 case Q3DEFORM_AUTOSPRITE:
8462 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8463 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8464 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8465 VectorNormalize(newforward);
8466 VectorNormalize(newright);
8467 VectorNormalize(newup);
8468 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8469 // rsurface.batchvertex3f_vertexbuffer = NULL;
8470 // rsurface.batchvertex3f_bufferoffset = 0;
8471 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8472 // rsurface.batchsvector3f_vertexbuffer = NULL;
8473 // rsurface.batchsvector3f_bufferoffset = 0;
8474 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8475 // rsurface.batchtvector3f_vertexbuffer = NULL;
8476 // rsurface.batchtvector3f_bufferoffset = 0;
8477 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8478 // rsurface.batchnormal3f_vertexbuffer = NULL;
8479 // rsurface.batchnormal3f_bufferoffset = 0;
8480 // a single autosprite surface can contain multiple sprites...
8481 for (j = 0;j < batchnumvertices - 3;j += 4)
8483 VectorClear(center);
8484 for (i = 0;i < 4;i++)
8485 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8486 VectorScale(center, 0.25f, center);
8487 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8488 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8489 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8490 for (i = 0;i < 4;i++)
8492 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8493 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8496 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8497 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8498 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);
8500 case Q3DEFORM_AUTOSPRITE2:
8501 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8502 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8503 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8504 VectorNormalize(newforward);
8505 VectorNormalize(newright);
8506 VectorNormalize(newup);
8507 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8508 // rsurface.batchvertex3f_vertexbuffer = NULL;
8509 // rsurface.batchvertex3f_bufferoffset = 0;
8511 const float *v1, *v2;
8521 memset(shortest, 0, sizeof(shortest));
8522 // a single autosprite surface can contain multiple sprites...
8523 for (j = 0;j < batchnumvertices - 3;j += 4)
8525 VectorClear(center);
8526 for (i = 0;i < 4;i++)
8527 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8528 VectorScale(center, 0.25f, center);
8529 // find the two shortest edges, then use them to define the
8530 // axis vectors for rotating around the central axis
8531 for (i = 0;i < 6;i++)
8533 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8534 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8535 l = VectorDistance2(v1, v2);
8536 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8538 l += (1.0f / 1024.0f);
8539 if (shortest[0].length2 > l || i == 0)
8541 shortest[1] = shortest[0];
8542 shortest[0].length2 = l;
8543 shortest[0].v1 = v1;
8544 shortest[0].v2 = v2;
8546 else if (shortest[1].length2 > l || i == 1)
8548 shortest[1].length2 = l;
8549 shortest[1].v1 = v1;
8550 shortest[1].v2 = v2;
8553 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8554 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8555 // this calculates the right vector from the shortest edge
8556 // and the up vector from the edge midpoints
8557 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8558 VectorNormalize(right);
8559 VectorSubtract(end, start, up);
8560 VectorNormalize(up);
8561 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8562 VectorSubtract(rsurface.localvieworigin, center, forward);
8563 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8564 VectorNegate(forward, forward);
8565 VectorReflect(forward, 0, up, forward);
8566 VectorNormalize(forward);
8567 CrossProduct(up, forward, newright);
8568 VectorNormalize(newright);
8569 // rotate the quad around the up axis vector, this is made
8570 // especially easy by the fact we know the quad is flat,
8571 // so we only have to subtract the center position and
8572 // measure distance along the right vector, and then
8573 // multiply that by the newright vector and add back the
8575 // we also need to subtract the old position to undo the
8576 // displacement from the center, which we do with a
8577 // DotProduct, the subtraction/addition of center is also
8578 // optimized into DotProducts here
8579 l = DotProduct(right, center);
8580 for (i = 0;i < 4;i++)
8582 v1 = rsurface.batchvertex3f + 3*(j+i);
8583 f = DotProduct(right, v1) - l;
8584 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8588 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8590 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8591 // rsurface.batchnormal3f_vertexbuffer = NULL;
8592 // rsurface.batchnormal3f_bufferoffset = 0;
8593 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8595 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8597 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8598 // rsurface.batchsvector3f_vertexbuffer = NULL;
8599 // rsurface.batchsvector3f_bufferoffset = 0;
8600 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8601 // rsurface.batchtvector3f_vertexbuffer = NULL;
8602 // rsurface.batchtvector3f_bufferoffset = 0;
8603 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);
8606 case Q3DEFORM_NORMAL:
8607 // deform the normals to make reflections wavey
8608 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8609 rsurface.batchnormal3f_vertexbuffer = NULL;
8610 rsurface.batchnormal3f_bufferoffset = 0;
8611 for (j = 0;j < batchnumvertices;j++)
8614 float *normal = rsurface.batchnormal3f + 3*j;
8615 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8616 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8617 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]);
8618 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]);
8619 VectorNormalize(normal);
8621 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8623 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8624 // rsurface.batchsvector3f_vertexbuffer = NULL;
8625 // rsurface.batchsvector3f_bufferoffset = 0;
8626 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8627 // rsurface.batchtvector3f_vertexbuffer = NULL;
8628 // rsurface.batchtvector3f_bufferoffset = 0;
8629 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);
8633 // deform vertex array to make wavey water and flags and such
8634 waveparms[0] = deform->waveparms[0];
8635 waveparms[1] = deform->waveparms[1];
8636 waveparms[2] = deform->waveparms[2];
8637 waveparms[3] = deform->waveparms[3];
8638 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8639 break; // if wavefunc is a nop, don't make a dynamic vertex array
8640 // this is how a divisor of vertex influence on deformation
8641 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8642 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8643 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8644 // rsurface.batchvertex3f_vertexbuffer = NULL;
8645 // rsurface.batchvertex3f_bufferoffset = 0;
8646 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8647 // rsurface.batchnormal3f_vertexbuffer = NULL;
8648 // rsurface.batchnormal3f_bufferoffset = 0;
8649 for (j = 0;j < batchnumvertices;j++)
8651 // if the wavefunc depends on time, evaluate it per-vertex
8654 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8655 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8657 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8659 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8660 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8661 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8663 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8664 // rsurface.batchsvector3f_vertexbuffer = NULL;
8665 // rsurface.batchsvector3f_bufferoffset = 0;
8666 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8667 // rsurface.batchtvector3f_vertexbuffer = NULL;
8668 // rsurface.batchtvector3f_bufferoffset = 0;
8669 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);
8672 case Q3DEFORM_BULGE:
8673 // deform vertex array to make the surface have moving bulges
8674 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8675 // rsurface.batchvertex3f_vertexbuffer = NULL;
8676 // rsurface.batchvertex3f_bufferoffset = 0;
8677 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8678 // rsurface.batchnormal3f_vertexbuffer = NULL;
8679 // rsurface.batchnormal3f_bufferoffset = 0;
8680 for (j = 0;j < batchnumvertices;j++)
8682 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8683 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8685 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8686 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8687 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8689 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8690 // rsurface.batchsvector3f_vertexbuffer = NULL;
8691 // rsurface.batchsvector3f_bufferoffset = 0;
8692 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8693 // rsurface.batchtvector3f_vertexbuffer = NULL;
8694 // rsurface.batchtvector3f_bufferoffset = 0;
8695 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);
8699 // deform vertex array
8700 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8701 break; // if wavefunc is a nop, don't make a dynamic vertex array
8702 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8703 VectorScale(deform->parms, scale, waveparms);
8704 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8705 // rsurface.batchvertex3f_vertexbuffer = NULL;
8706 // rsurface.batchvertex3f_bufferoffset = 0;
8707 for (j = 0;j < batchnumvertices;j++)
8708 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8713 // generate texcoords based on the chosen texcoord source
8714 switch(rsurface.texture->tcgen.tcgen)
8717 case Q3TCGEN_TEXTURE:
8719 case Q3TCGEN_LIGHTMAP:
8720 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8721 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8722 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8723 if (rsurface.batchtexcoordlightmap2f)
8724 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8726 case Q3TCGEN_VECTOR:
8727 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8728 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8729 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8730 for (j = 0;j < batchnumvertices;j++)
8732 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8733 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8736 case Q3TCGEN_ENVIRONMENT:
8737 // make environment reflections using a spheremap
8738 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8739 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8740 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8741 for (j = 0;j < batchnumvertices;j++)
8743 // identical to Q3A's method, but executed in worldspace so
8744 // carried models can be shiny too
8746 float viewer[3], d, reflected[3], worldreflected[3];
8748 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8749 // VectorNormalize(viewer);
8751 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8753 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8754 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8755 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8756 // note: this is proportinal to viewer, so we can normalize later
8758 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8759 VectorNormalize(worldreflected);
8761 // note: this sphere map only uses world x and z!
8762 // so positive and negative y will LOOK THE SAME.
8763 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8764 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8768 // the only tcmod that needs software vertex processing is turbulent, so
8769 // check for it here and apply the changes if needed
8770 // and we only support that as the first one
8771 // (handling a mixture of turbulent and other tcmods would be problematic
8772 // without punting it entirely to a software path)
8773 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8775 amplitude = rsurface.texture->tcmods[0].parms[1];
8776 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8777 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8778 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8779 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8780 for (j = 0;j < batchnumvertices;j++)
8782 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);
8783 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8787 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8789 // convert the modified arrays to vertex structs
8790 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8791 // rsurface.batchvertexmeshbuffer = NULL;
8792 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8793 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8794 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8795 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8796 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8797 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8798 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8800 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8802 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8803 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8806 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8807 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8808 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8809 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8810 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8811 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8812 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8813 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8814 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8818 void RSurf_DrawBatch(void)
8820 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8821 // through the pipeline, killing it earlier in the pipeline would have
8822 // per-surface overhead rather than per-batch overhead, so it's best to
8823 // reject it here, before it hits glDraw.
8824 if (rsurface.batchnumtriangles == 0)
8827 // batch debugging code
8828 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8834 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8835 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8838 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8840 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8842 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8843 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);
8850 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);
8853 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8855 // pick the closest matching water plane
8856 int planeindex, vertexindex, bestplaneindex = -1;
8860 r_waterstate_waterplane_t *p;
8861 qboolean prepared = false;
8863 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8865 if(p->camera_entity != rsurface.texture->camera_entity)
8870 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8872 if(rsurface.batchnumvertices == 0)
8875 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8877 Matrix4x4_Transform(&rsurface.matrix, v, vert);
8878 d += fabs(PlaneDiff(vert, &p->plane));
8880 if (bestd > d || bestplaneindex < 0)
8883 bestplaneindex = planeindex;
8886 return bestplaneindex;
8887 // NOTE: this MAY return a totally unrelated water plane; we can ignore
8888 // this situation though, as it might be better to render single larger
8889 // batches with useless stuff (backface culled for example) than to
8890 // render multiple smaller batches
8893 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8896 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8897 rsurface.passcolor4f_vertexbuffer = 0;
8898 rsurface.passcolor4f_bufferoffset = 0;
8899 for (i = 0;i < rsurface.batchnumvertices;i++)
8900 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8903 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8910 if (rsurface.passcolor4f)
8912 // generate color arrays
8913 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8914 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8915 rsurface.passcolor4f_vertexbuffer = 0;
8916 rsurface.passcolor4f_bufferoffset = 0;
8917 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)
8919 f = RSurf_FogVertex(v);
8928 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8929 rsurface.passcolor4f_vertexbuffer = 0;
8930 rsurface.passcolor4f_bufferoffset = 0;
8931 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8933 f = RSurf_FogVertex(v);
8942 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8949 if (!rsurface.passcolor4f)
8951 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8952 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8953 rsurface.passcolor4f_vertexbuffer = 0;
8954 rsurface.passcolor4f_bufferoffset = 0;
8955 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)
8957 f = RSurf_FogVertex(v);
8958 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8959 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8960 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8965 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
8970 if (!rsurface.passcolor4f)
8972 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8973 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8974 rsurface.passcolor4f_vertexbuffer = 0;
8975 rsurface.passcolor4f_bufferoffset = 0;
8976 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
8985 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
8990 if (!rsurface.passcolor4f)
8992 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8993 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8994 rsurface.passcolor4f_vertexbuffer = 0;
8995 rsurface.passcolor4f_bufferoffset = 0;
8996 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
8998 c2[0] = c[0] + r_refdef.scene.ambient;
8999 c2[1] = c[1] + r_refdef.scene.ambient;
9000 c2[2] = c[2] + r_refdef.scene.ambient;
9005 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9008 rsurface.passcolor4f = NULL;
9009 rsurface.passcolor4f_vertexbuffer = 0;
9010 rsurface.passcolor4f_bufferoffset = 0;
9011 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9012 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9013 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9014 GL_Color(r, g, b, a);
9015 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9019 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9021 // TODO: optimize applyfog && applycolor case
9022 // just apply fog if necessary, and tint the fog color array if necessary
9023 rsurface.passcolor4f = NULL;
9024 rsurface.passcolor4f_vertexbuffer = 0;
9025 rsurface.passcolor4f_bufferoffset = 0;
9026 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9027 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9028 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9029 GL_Color(r, g, b, a);
9033 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9036 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9037 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9038 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9039 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9040 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9041 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9042 GL_Color(r, g, b, a);
9046 static void RSurf_DrawBatch_GL11_ClampColor(void)
9051 if (!rsurface.passcolor4f)
9053 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9055 c2[0] = bound(0.0f, c1[0], 1.0f);
9056 c2[1] = bound(0.0f, c1[1], 1.0f);
9057 c2[2] = bound(0.0f, c1[2], 1.0f);
9058 c2[3] = bound(0.0f, c1[3], 1.0f);
9062 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9072 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9073 rsurface.passcolor4f_vertexbuffer = 0;
9074 rsurface.passcolor4f_bufferoffset = 0;
9075 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)
9077 f = -DotProduct(r_refdef.view.forward, n);
9079 f = f * 0.85 + 0.15; // work around so stuff won't get black
9080 f *= r_refdef.lightmapintensity;
9081 Vector4Set(c, f, f, f, 1);
9085 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9087 RSurf_DrawBatch_GL11_ApplyFakeLight();
9088 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9089 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9090 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9091 GL_Color(r, g, b, a);
9095 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9103 vec3_t ambientcolor;
9104 vec3_t diffusecolor;
9108 VectorCopy(rsurface.modellight_lightdir, lightdir);
9109 f = 0.5f * r_refdef.lightmapintensity;
9110 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9111 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9112 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9113 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9114 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9115 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9117 if (VectorLength2(diffusecolor) > 0)
9119 // q3-style directional shading
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 if ((f = DotProduct(n, lightdir)) > 0)
9126 VectorMA(ambientcolor, f, diffusecolor, c);
9128 VectorCopy(ambientcolor, c);
9135 *applycolor = false;
9139 *r = ambientcolor[0];
9140 *g = ambientcolor[1];
9141 *b = ambientcolor[2];
9142 rsurface.passcolor4f = NULL;
9143 rsurface.passcolor4f_vertexbuffer = 0;
9144 rsurface.passcolor4f_bufferoffset = 0;
9148 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9150 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9151 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9152 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9153 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9154 GL_Color(r, g, b, a);
9158 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9164 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9166 f = 1 - RSurf_FogVertex(v);
9174 void RSurf_SetupDepthAndCulling(void)
9176 // submodels are biased to avoid z-fighting with world surfaces that they
9177 // may be exactly overlapping (avoids z-fighting artifacts on certain
9178 // doors and things in Quake maps)
9179 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9180 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9181 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9182 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9185 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9187 // transparent sky would be ridiculous
9188 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9190 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9191 skyrenderlater = true;
9192 RSurf_SetupDepthAndCulling();
9194 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9195 // skymasking on them, and Quake3 never did sky masking (unlike
9196 // software Quake and software Quake2), so disable the sky masking
9197 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9198 // and skymasking also looks very bad when noclipping outside the
9199 // level, so don't use it then either.
9200 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9202 R_Mesh_ResetTextureState();
9203 if (skyrendermasked)
9205 R_SetupShader_DepthOrShadow();
9206 // depth-only (masking)
9207 GL_ColorMask(0,0,0,0);
9208 // just to make sure that braindead drivers don't draw
9209 // anything despite that colormask...
9210 GL_BlendFunc(GL_ZERO, GL_ONE);
9211 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9212 if (rsurface.batchvertex3fbuffer)
9213 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9215 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9219 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9221 GL_BlendFunc(GL_ONE, GL_ZERO);
9222 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9223 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9224 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9227 if (skyrendermasked)
9228 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9230 R_Mesh_ResetTextureState();
9231 GL_Color(1, 1, 1, 1);
9234 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9235 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9236 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9238 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9242 // render screenspace normalmap to texture
9244 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9249 // bind lightmap texture
9251 // water/refraction/reflection/camera surfaces have to be handled specially
9252 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9254 int start, end, startplaneindex;
9255 for (start = 0;start < texturenumsurfaces;start = end)
9257 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9258 if(startplaneindex < 0)
9260 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9261 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9265 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9267 // now that we have a batch using the same planeindex, render it
9268 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9270 // render water or distortion background
9272 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));
9274 // blend surface on top
9275 GL_DepthMask(false);
9276 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9279 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9281 // render surface with reflection texture as input
9282 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9283 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));
9290 // render surface batch normally
9291 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9292 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9296 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9298 // OpenGL 1.3 path - anything not completely ancient
9299 qboolean applycolor;
9302 const texturelayer_t *layer;
9303 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);
9304 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9306 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9309 int layertexrgbscale;
9310 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9312 if (layerindex == 0)
9316 GL_AlphaTest(false);
9317 GL_DepthFunc(GL_EQUAL);
9320 GL_DepthMask(layer->depthmask && writedepth);
9321 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9322 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9324 layertexrgbscale = 4;
9325 VectorScale(layer->color, 0.25f, layercolor);
9327 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9329 layertexrgbscale = 2;
9330 VectorScale(layer->color, 0.5f, layercolor);
9334 layertexrgbscale = 1;
9335 VectorScale(layer->color, 1.0f, layercolor);
9337 layercolor[3] = layer->color[3];
9338 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9339 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9340 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9341 switch (layer->type)
9343 case TEXTURELAYERTYPE_LITTEXTURE:
9344 // single-pass lightmapped texture with 2x rgbscale
9345 R_Mesh_TexBind(0, r_texture_white);
9346 R_Mesh_TexMatrix(0, NULL);
9347 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9348 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9349 R_Mesh_TexBind(1, layer->texture);
9350 R_Mesh_TexMatrix(1, &layer->texmatrix);
9351 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9352 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9353 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9354 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9355 else if (FAKELIGHT_ENABLED)
9356 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9357 else if (rsurface.uselightmaptexture)
9358 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9360 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9362 case TEXTURELAYERTYPE_TEXTURE:
9363 // singletexture unlit texture with transparency support
9364 R_Mesh_TexBind(0, layer->texture);
9365 R_Mesh_TexMatrix(0, &layer->texmatrix);
9366 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9367 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9368 R_Mesh_TexBind(1, 0);
9369 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9370 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9372 case TEXTURELAYERTYPE_FOG:
9373 // singletexture fogging
9376 R_Mesh_TexBind(0, layer->texture);
9377 R_Mesh_TexMatrix(0, &layer->texmatrix);
9378 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9379 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9383 R_Mesh_TexBind(0, 0);
9384 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9386 R_Mesh_TexBind(1, 0);
9387 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9388 // generate a color array for the fog pass
9389 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9390 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9394 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9397 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9399 GL_DepthFunc(GL_LEQUAL);
9400 GL_AlphaTest(false);
9404 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9406 // OpenGL 1.1 - crusty old voodoo path
9409 const texturelayer_t *layer;
9410 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);
9411 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9413 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9415 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9417 if (layerindex == 0)
9421 GL_AlphaTest(false);
9422 GL_DepthFunc(GL_EQUAL);
9425 GL_DepthMask(layer->depthmask && writedepth);
9426 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9427 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9428 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9429 switch (layer->type)
9431 case TEXTURELAYERTYPE_LITTEXTURE:
9432 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9434 // two-pass lit texture with 2x rgbscale
9435 // first the lightmap pass
9436 R_Mesh_TexBind(0, r_texture_white);
9437 R_Mesh_TexMatrix(0, NULL);
9438 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9439 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9440 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9441 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9442 else if (FAKELIGHT_ENABLED)
9443 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9444 else if (rsurface.uselightmaptexture)
9445 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9447 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9448 // then apply the texture to it
9449 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9450 R_Mesh_TexBind(0, layer->texture);
9451 R_Mesh_TexMatrix(0, &layer->texmatrix);
9452 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9453 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9454 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);
9458 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9459 R_Mesh_TexBind(0, layer->texture);
9460 R_Mesh_TexMatrix(0, &layer->texmatrix);
9461 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9462 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9463 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9464 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);
9466 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);
9469 case TEXTURELAYERTYPE_TEXTURE:
9470 // singletexture unlit texture with transparency support
9471 R_Mesh_TexBind(0, layer->texture);
9472 R_Mesh_TexMatrix(0, &layer->texmatrix);
9473 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9474 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9475 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);
9477 case TEXTURELAYERTYPE_FOG:
9478 // singletexture fogging
9481 R_Mesh_TexBind(0, layer->texture);
9482 R_Mesh_TexMatrix(0, &layer->texmatrix);
9483 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9484 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9488 R_Mesh_TexBind(0, 0);
9489 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9491 // generate a color array for the fog pass
9492 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9493 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9497 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9500 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9502 GL_DepthFunc(GL_LEQUAL);
9503 GL_AlphaTest(false);
9507 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9511 r_vertexgeneric_t *batchvertex;
9514 // R_Mesh_ResetTextureState();
9515 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9517 if(rsurface.texture && rsurface.texture->currentskinframe)
9519 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9520 c[3] *= rsurface.texture->currentalpha;
9530 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9532 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9533 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9534 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9537 // brighten it up (as texture value 127 means "unlit")
9538 c[0] *= 2 * r_refdef.view.colorscale;
9539 c[1] *= 2 * r_refdef.view.colorscale;
9540 c[2] *= 2 * r_refdef.view.colorscale;
9542 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9543 c[3] *= r_wateralpha.value;
9545 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9547 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9548 GL_DepthMask(false);
9550 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9552 GL_BlendFunc(GL_ONE, GL_ONE);
9553 GL_DepthMask(false);
9555 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9557 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9558 GL_DepthMask(false);
9560 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9562 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9563 GL_DepthMask(false);
9567 GL_BlendFunc(GL_ONE, GL_ZERO);
9568 GL_DepthMask(writedepth);
9571 if (r_showsurfaces.integer == 3)
9573 rsurface.passcolor4f = NULL;
9575 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9577 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9579 rsurface.passcolor4f = NULL;
9580 rsurface.passcolor4f_vertexbuffer = 0;
9581 rsurface.passcolor4f_bufferoffset = 0;
9583 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9585 qboolean applycolor = true;
9588 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9590 r_refdef.lightmapintensity = 1;
9591 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9592 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9594 else if (FAKELIGHT_ENABLED)
9596 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9598 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9599 RSurf_DrawBatch_GL11_ApplyFakeLight();
9600 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9604 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9606 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9607 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9608 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9611 if(!rsurface.passcolor4f)
9612 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9614 RSurf_DrawBatch_GL11_ApplyAmbient();
9615 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9616 if(r_refdef.fogenabled)
9617 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9618 RSurf_DrawBatch_GL11_ClampColor();
9620 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9621 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9624 else if (!r_refdef.view.showdebug)
9626 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9627 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9628 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9630 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9631 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9633 R_Mesh_PrepareVertices_Generic_Unlock();
9636 else if (r_showsurfaces.integer == 4)
9638 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9639 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9640 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9642 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9643 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9644 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9646 R_Mesh_PrepareVertices_Generic_Unlock();
9649 else if (r_showsurfaces.integer == 2)
9652 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9653 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9654 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9656 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9657 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9658 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9659 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9660 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9661 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9662 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9664 R_Mesh_PrepareVertices_Generic_Unlock();
9665 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9669 int texturesurfaceindex;
9671 const msurface_t *surface;
9672 float surfacecolor4f[4];
9673 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9674 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9676 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9678 surface = texturesurfacelist[texturesurfaceindex];
9679 k = (int)(((size_t)surface) / sizeof(msurface_t));
9680 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9681 for (j = 0;j < surface->num_vertices;j++)
9683 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9684 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9688 R_Mesh_PrepareVertices_Generic_Unlock();
9693 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9696 RSurf_SetupDepthAndCulling();
9697 if (r_showsurfaces.integer)
9699 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9702 switch (vid.renderpath)
9704 case RENDERPATH_GL20:
9705 case RENDERPATH_D3D9:
9706 case RENDERPATH_D3D10:
9707 case RENDERPATH_D3D11:
9708 case RENDERPATH_SOFT:
9709 case RENDERPATH_GLES2:
9710 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9712 case RENDERPATH_GL13:
9713 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9715 case RENDERPATH_GL11:
9716 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9722 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9725 RSurf_SetupDepthAndCulling();
9726 if (r_showsurfaces.integer)
9728 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9731 switch (vid.renderpath)
9733 case RENDERPATH_GL20:
9734 case RENDERPATH_D3D9:
9735 case RENDERPATH_D3D10:
9736 case RENDERPATH_D3D11:
9737 case RENDERPATH_SOFT:
9738 case RENDERPATH_GLES2:
9739 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9741 case RENDERPATH_GL13:
9742 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9744 case RENDERPATH_GL11:
9745 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9751 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9754 int texturenumsurfaces, endsurface;
9756 const msurface_t *surface;
9757 #define MAXBATCH_TRANSPARENTSURFACES 256
9758 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9760 // if the model is static it doesn't matter what value we give for
9761 // wantnormals and wanttangents, so this logic uses only rules applicable
9762 // to a model, knowing that they are meaningless otherwise
9763 if (ent == r_refdef.scene.worldentity)
9764 RSurf_ActiveWorldEntity();
9765 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9766 RSurf_ActiveModelEntity(ent, false, false, false);
9769 switch (vid.renderpath)
9771 case RENDERPATH_GL20:
9772 case RENDERPATH_D3D9:
9773 case RENDERPATH_D3D10:
9774 case RENDERPATH_D3D11:
9775 case RENDERPATH_SOFT:
9776 case RENDERPATH_GLES2:
9777 RSurf_ActiveModelEntity(ent, true, true, false);
9779 case RENDERPATH_GL13:
9780 case RENDERPATH_GL11:
9781 RSurf_ActiveModelEntity(ent, true, false, false);
9786 if (r_transparentdepthmasking.integer)
9788 qboolean setup = false;
9789 for (i = 0;i < numsurfaces;i = j)
9792 surface = rsurface.modelsurfaces + surfacelist[i];
9793 texture = surface->texture;
9794 rsurface.texture = R_GetCurrentTexture(texture);
9795 rsurface.lightmaptexture = NULL;
9796 rsurface.deluxemaptexture = NULL;
9797 rsurface.uselightmaptexture = false;
9798 // scan ahead until we find a different texture
9799 endsurface = min(i + 1024, numsurfaces);
9800 texturenumsurfaces = 0;
9801 texturesurfacelist[texturenumsurfaces++] = surface;
9802 for (;j < endsurface;j++)
9804 surface = rsurface.modelsurfaces + surfacelist[j];
9805 if (texture != surface->texture)
9807 texturesurfacelist[texturenumsurfaces++] = surface;
9809 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9811 // render the range of surfaces as depth
9815 GL_ColorMask(0,0,0,0);
9818 GL_BlendFunc(GL_ONE, GL_ZERO);
9820 // R_Mesh_ResetTextureState();
9821 R_SetupShader_DepthOrShadow();
9823 RSurf_SetupDepthAndCulling();
9824 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9825 if (rsurface.batchvertex3fbuffer)
9826 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9828 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9832 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9835 for (i = 0;i < numsurfaces;i = j)
9838 surface = rsurface.modelsurfaces + surfacelist[i];
9839 texture = surface->texture;
9840 rsurface.texture = R_GetCurrentTexture(texture);
9841 // scan ahead until we find a different texture
9842 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9843 texturenumsurfaces = 0;
9844 texturesurfacelist[texturenumsurfaces++] = surface;
9845 if(FAKELIGHT_ENABLED)
9847 rsurface.lightmaptexture = NULL;
9848 rsurface.deluxemaptexture = NULL;
9849 rsurface.uselightmaptexture = false;
9850 for (;j < endsurface;j++)
9852 surface = rsurface.modelsurfaces + surfacelist[j];
9853 if (texture != surface->texture)
9855 texturesurfacelist[texturenumsurfaces++] = surface;
9860 rsurface.lightmaptexture = surface->lightmaptexture;
9861 rsurface.deluxemaptexture = surface->deluxemaptexture;
9862 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9863 for (;j < endsurface;j++)
9865 surface = rsurface.modelsurfaces + surfacelist[j];
9866 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9868 texturesurfacelist[texturenumsurfaces++] = surface;
9871 // render the range of surfaces
9872 if (ent == r_refdef.scene.worldentity)
9873 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9875 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9877 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9880 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9882 // transparent surfaces get pushed off into the transparent queue
9883 int surfacelistindex;
9884 const msurface_t *surface;
9885 vec3_t tempcenter, center;
9886 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9888 surface = texturesurfacelist[surfacelistindex];
9889 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9890 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9891 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9892 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9893 if (queueentity->transparent_offset) // transparent offset
9895 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9896 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9897 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9899 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9903 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9905 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9907 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9909 RSurf_SetupDepthAndCulling();
9910 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9911 if (rsurface.batchvertex3fbuffer)
9912 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9914 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9918 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9920 const entity_render_t *queueentity = r_refdef.scene.worldentity;
9923 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9926 if (!rsurface.texture->currentnumlayers)
9928 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9929 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9931 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9933 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9934 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9935 else if (!rsurface.texture->currentnumlayers)
9937 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9939 // in the deferred case, transparent surfaces were queued during prepass
9940 if (!r_shadow_usingdeferredprepass)
9941 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9945 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9946 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9951 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9955 R_FrameData_SetMark();
9956 // break the surface list down into batches by texture and use of lightmapping
9957 for (i = 0;i < numsurfaces;i = j)
9960 // texture is the base texture pointer, rsurface.texture is the
9961 // current frame/skin the texture is directing us to use (for example
9962 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9963 // use skin 1 instead)
9964 texture = surfacelist[i]->texture;
9965 rsurface.texture = R_GetCurrentTexture(texture);
9966 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9968 // if this texture is not the kind we want, skip ahead to the next one
9969 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9973 if(FAKELIGHT_ENABLED || depthonly || prepass)
9975 rsurface.lightmaptexture = NULL;
9976 rsurface.deluxemaptexture = NULL;
9977 rsurface.uselightmaptexture = false;
9978 // simply scan ahead until we find a different texture or lightmap state
9979 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9984 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
9985 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
9986 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
9987 // simply scan ahead until we find a different texture or lightmap state
9988 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
9991 // render the range of surfaces
9992 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
9994 R_FrameData_ReturnToMark();
9997 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10001 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10004 if (!rsurface.texture->currentnumlayers)
10006 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10007 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10009 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10011 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10012 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10013 else if (!rsurface.texture->currentnumlayers)
10015 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10017 // in the deferred case, transparent surfaces were queued during prepass
10018 if (!r_shadow_usingdeferredprepass)
10019 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10023 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10024 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10029 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10032 texture_t *texture;
10033 R_FrameData_SetMark();
10034 // break the surface list down into batches by texture and use of lightmapping
10035 for (i = 0;i < numsurfaces;i = j)
10038 // texture is the base texture pointer, rsurface.texture is the
10039 // current frame/skin the texture is directing us to use (for example
10040 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10041 // use skin 1 instead)
10042 texture = surfacelist[i]->texture;
10043 rsurface.texture = R_GetCurrentTexture(texture);
10044 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10046 // if this texture is not the kind we want, skip ahead to the next one
10047 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10051 if(FAKELIGHT_ENABLED || depthonly || prepass)
10053 rsurface.lightmaptexture = NULL;
10054 rsurface.deluxemaptexture = NULL;
10055 rsurface.uselightmaptexture = false;
10056 // simply scan ahead until we find a different texture or lightmap state
10057 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10062 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10063 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10064 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10065 // simply scan ahead until we find a different texture or lightmap state
10066 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10069 // render the range of surfaces
10070 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10072 R_FrameData_ReturnToMark();
10075 float locboxvertex3f[6*4*3] =
10077 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10078 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10079 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10080 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10081 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10082 1,0,0, 0,0,0, 0,1,0, 1,1,0
10085 unsigned short locboxelements[6*2*3] =
10090 12,13,14, 12,14,15,
10091 16,17,18, 16,18,19,
10095 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10098 cl_locnode_t *loc = (cl_locnode_t *)ent;
10100 float vertex3f[6*4*3];
10102 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10103 GL_DepthMask(false);
10104 GL_DepthRange(0, 1);
10105 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10106 GL_DepthTest(true);
10107 GL_CullFace(GL_NONE);
10108 R_EntityMatrix(&identitymatrix);
10110 // R_Mesh_ResetTextureState();
10112 i = surfacelist[0];
10113 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10114 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10115 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10116 surfacelist[0] < 0 ? 0.5f : 0.125f);
10118 if (VectorCompare(loc->mins, loc->maxs))
10120 VectorSet(size, 2, 2, 2);
10121 VectorMA(loc->mins, -0.5f, size, mins);
10125 VectorCopy(loc->mins, mins);
10126 VectorSubtract(loc->maxs, loc->mins, size);
10129 for (i = 0;i < 6*4*3;)
10130 for (j = 0;j < 3;j++, i++)
10131 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10133 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10134 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10135 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10138 void R_DrawLocs(void)
10141 cl_locnode_t *loc, *nearestloc;
10143 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10144 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10146 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10147 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10151 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10153 if (decalsystem->decals)
10154 Mem_Free(decalsystem->decals);
10155 memset(decalsystem, 0, sizeof(*decalsystem));
10158 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)
10161 tridecal_t *decals;
10164 // expand or initialize the system
10165 if (decalsystem->maxdecals <= decalsystem->numdecals)
10167 decalsystem_t old = *decalsystem;
10168 qboolean useshortelements;
10169 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10170 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10171 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)));
10172 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10173 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10174 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10175 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10176 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10177 if (decalsystem->numdecals)
10178 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10180 Mem_Free(old.decals);
10181 for (i = 0;i < decalsystem->maxdecals*3;i++)
10182 decalsystem->element3i[i] = i;
10183 if (useshortelements)
10184 for (i = 0;i < decalsystem->maxdecals*3;i++)
10185 decalsystem->element3s[i] = i;
10188 // grab a decal and search for another free slot for the next one
10189 decals = decalsystem->decals;
10190 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10191 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10193 decalsystem->freedecal = i;
10194 if (decalsystem->numdecals <= i)
10195 decalsystem->numdecals = i + 1;
10197 // initialize the decal
10199 decal->triangleindex = triangleindex;
10200 decal->surfaceindex = surfaceindex;
10201 decal->decalsequence = decalsequence;
10202 decal->color4f[0][0] = c0[0];
10203 decal->color4f[0][1] = c0[1];
10204 decal->color4f[0][2] = c0[2];
10205 decal->color4f[0][3] = 1;
10206 decal->color4f[1][0] = c1[0];
10207 decal->color4f[1][1] = c1[1];
10208 decal->color4f[1][2] = c1[2];
10209 decal->color4f[1][3] = 1;
10210 decal->color4f[2][0] = c2[0];
10211 decal->color4f[2][1] = c2[1];
10212 decal->color4f[2][2] = c2[2];
10213 decal->color4f[2][3] = 1;
10214 decal->vertex3f[0][0] = v0[0];
10215 decal->vertex3f[0][1] = v0[1];
10216 decal->vertex3f[0][2] = v0[2];
10217 decal->vertex3f[1][0] = v1[0];
10218 decal->vertex3f[1][1] = v1[1];
10219 decal->vertex3f[1][2] = v1[2];
10220 decal->vertex3f[2][0] = v2[0];
10221 decal->vertex3f[2][1] = v2[1];
10222 decal->vertex3f[2][2] = v2[2];
10223 decal->texcoord2f[0][0] = t0[0];
10224 decal->texcoord2f[0][1] = t0[1];
10225 decal->texcoord2f[1][0] = t1[0];
10226 decal->texcoord2f[1][1] = t1[1];
10227 decal->texcoord2f[2][0] = t2[0];
10228 decal->texcoord2f[2][1] = t2[1];
10231 extern cvar_t cl_decals_bias;
10232 extern cvar_t cl_decals_models;
10233 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10234 // baseparms, parms, temps
10235 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)
10240 const float *vertex3f;
10241 const float *normal3f;
10243 float points[2][9][3];
10250 e = rsurface.modelelement3i + 3*triangleindex;
10252 vertex3f = rsurface.modelvertex3f;
10253 normal3f = rsurface.modelnormal3f;
10255 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10257 index = 3*e[cornerindex];
10258 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10261 //TriangleNormal(v[0], v[1], v[2], normal);
10262 //if (DotProduct(normal, localnormal) < 0.0f)
10264 // clip by each of the box planes formed from the projection matrix
10265 // if anything survives, we emit the decal
10266 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]);
10269 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]);
10272 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]);
10275 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]);
10278 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]);
10281 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]);
10284 // some part of the triangle survived, so we have to accept it...
10287 // dynamic always uses the original triangle
10289 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10291 index = 3*e[cornerindex];
10292 VectorCopy(vertex3f + index, v[cornerindex]);
10295 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10297 // convert vertex positions to texcoords
10298 Matrix4x4_Transform(projection, v[cornerindex], temp);
10299 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10300 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10301 // calculate distance fade from the projection origin
10302 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10303 f = bound(0.0f, f, 1.0f);
10304 c[cornerindex][0] = r * f;
10305 c[cornerindex][1] = g * f;
10306 c[cornerindex][2] = b * f;
10307 c[cornerindex][3] = 1.0f;
10308 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10311 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);
10313 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10314 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);
10316 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)
10318 matrix4x4_t projection;
10319 decalsystem_t *decalsystem;
10322 const msurface_t *surface;
10323 const msurface_t *surfaces;
10324 const int *surfacelist;
10325 const texture_t *texture;
10327 int numsurfacelist;
10328 int surfacelistindex;
10331 float localorigin[3];
10332 float localnormal[3];
10333 float localmins[3];
10334 float localmaxs[3];
10337 float planes[6][4];
10340 int bih_triangles_count;
10341 int bih_triangles[256];
10342 int bih_surfaces[256];
10344 decalsystem = &ent->decalsystem;
10345 model = ent->model;
10346 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10348 R_DecalSystem_Reset(&ent->decalsystem);
10352 if (!model->brush.data_leafs && !cl_decals_models.integer)
10354 if (decalsystem->model)
10355 R_DecalSystem_Reset(decalsystem);
10359 if (decalsystem->model != model)
10360 R_DecalSystem_Reset(decalsystem);
10361 decalsystem->model = model;
10363 RSurf_ActiveModelEntity(ent, true, false, false);
10365 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10366 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10367 VectorNormalize(localnormal);
10368 localsize = worldsize*rsurface.inversematrixscale;
10369 localmins[0] = localorigin[0] - localsize;
10370 localmins[1] = localorigin[1] - localsize;
10371 localmins[2] = localorigin[2] - localsize;
10372 localmaxs[0] = localorigin[0] + localsize;
10373 localmaxs[1] = localorigin[1] + localsize;
10374 localmaxs[2] = localorigin[2] + localsize;
10376 //VectorCopy(localnormal, planes[4]);
10377 //VectorVectors(planes[4], planes[2], planes[0]);
10378 AnglesFromVectors(angles, localnormal, NULL, false);
10379 AngleVectors(angles, planes[0], planes[2], planes[4]);
10380 VectorNegate(planes[0], planes[1]);
10381 VectorNegate(planes[2], planes[3]);
10382 VectorNegate(planes[4], planes[5]);
10383 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10384 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10385 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10386 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10387 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10388 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10393 matrix4x4_t forwardprojection;
10394 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10395 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10400 float projectionvector[4][3];
10401 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10402 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10403 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10404 projectionvector[0][0] = planes[0][0] * ilocalsize;
10405 projectionvector[0][1] = planes[1][0] * ilocalsize;
10406 projectionvector[0][2] = planes[2][0] * ilocalsize;
10407 projectionvector[1][0] = planes[0][1] * ilocalsize;
10408 projectionvector[1][1] = planes[1][1] * ilocalsize;
10409 projectionvector[1][2] = planes[2][1] * ilocalsize;
10410 projectionvector[2][0] = planes[0][2] * ilocalsize;
10411 projectionvector[2][1] = planes[1][2] * ilocalsize;
10412 projectionvector[2][2] = planes[2][2] * ilocalsize;
10413 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10414 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10415 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10416 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10420 dynamic = model->surfmesh.isanimated;
10421 numsurfacelist = model->nummodelsurfaces;
10422 surfacelist = model->sortedmodelsurfaces;
10423 surfaces = model->data_surfaces;
10426 bih_triangles_count = -1;
10429 if(model->render_bih.numleafs)
10430 bih = &model->render_bih;
10431 else if(model->collision_bih.numleafs)
10432 bih = &model->collision_bih;
10435 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10436 if(bih_triangles_count == 0)
10438 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10440 if(bih_triangles_count > 0)
10442 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10444 surfaceindex = bih_surfaces[triangleindex];
10445 surface = surfaces + surfaceindex;
10446 texture = surface->texture;
10447 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10449 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10451 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10456 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10458 surfaceindex = surfacelist[surfacelistindex];
10459 surface = surfaces + surfaceindex;
10460 // check cull box first because it rejects more than any other check
10461 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10463 // skip transparent surfaces
10464 texture = surface->texture;
10465 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10467 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10469 numtriangles = surface->num_triangles;
10470 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10471 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10476 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10477 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)
10479 int renderentityindex;
10480 float worldmins[3];
10481 float worldmaxs[3];
10482 entity_render_t *ent;
10484 if (!cl_decals_newsystem.integer)
10487 worldmins[0] = worldorigin[0] - worldsize;
10488 worldmins[1] = worldorigin[1] - worldsize;
10489 worldmins[2] = worldorigin[2] - worldsize;
10490 worldmaxs[0] = worldorigin[0] + worldsize;
10491 worldmaxs[1] = worldorigin[1] + worldsize;
10492 worldmaxs[2] = worldorigin[2] + worldsize;
10494 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10496 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10498 ent = r_refdef.scene.entities[renderentityindex];
10499 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10502 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10506 typedef struct r_decalsystem_splatqueue_s
10508 vec3_t worldorigin;
10509 vec3_t worldnormal;
10515 r_decalsystem_splatqueue_t;
10517 int r_decalsystem_numqueued = 0;
10518 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10520 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)
10522 r_decalsystem_splatqueue_t *queue;
10524 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10527 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10528 VectorCopy(worldorigin, queue->worldorigin);
10529 VectorCopy(worldnormal, queue->worldnormal);
10530 Vector4Set(queue->color, r, g, b, a);
10531 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10532 queue->worldsize = worldsize;
10533 queue->decalsequence = cl.decalsequence++;
10536 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10539 r_decalsystem_splatqueue_t *queue;
10541 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10542 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);
10543 r_decalsystem_numqueued = 0;
10546 extern cvar_t cl_decals_max;
10547 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10550 decalsystem_t *decalsystem = &ent->decalsystem;
10557 if (!decalsystem->numdecals)
10560 if (r_showsurfaces.integer)
10563 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10565 R_DecalSystem_Reset(decalsystem);
10569 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10570 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10572 if (decalsystem->lastupdatetime)
10573 frametime = (cl.time - decalsystem->lastupdatetime);
10576 decalsystem->lastupdatetime = cl.time;
10577 decal = decalsystem->decals;
10578 numdecals = decalsystem->numdecals;
10580 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10582 if (decal->color4f[0][3])
10584 decal->lived += frametime;
10585 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10587 memset(decal, 0, sizeof(*decal));
10588 if (decalsystem->freedecal > i)
10589 decalsystem->freedecal = i;
10593 decal = decalsystem->decals;
10594 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10597 // collapse the array by shuffling the tail decals into the gaps
10600 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10601 decalsystem->freedecal++;
10602 if (decalsystem->freedecal == numdecals)
10604 decal[decalsystem->freedecal] = decal[--numdecals];
10607 decalsystem->numdecals = numdecals;
10609 if (numdecals <= 0)
10611 // if there are no decals left, reset decalsystem
10612 R_DecalSystem_Reset(decalsystem);
10616 extern skinframe_t *decalskinframe;
10617 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10620 decalsystem_t *decalsystem = &ent->decalsystem;
10629 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10632 numdecals = decalsystem->numdecals;
10636 if (r_showsurfaces.integer)
10639 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10641 R_DecalSystem_Reset(decalsystem);
10645 // if the model is static it doesn't matter what value we give for
10646 // wantnormals and wanttangents, so this logic uses only rules applicable
10647 // to a model, knowing that they are meaningless otherwise
10648 if (ent == r_refdef.scene.worldentity)
10649 RSurf_ActiveWorldEntity();
10651 RSurf_ActiveModelEntity(ent, false, false, false);
10653 decalsystem->lastupdatetime = cl.time;
10654 decal = decalsystem->decals;
10656 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10658 // update vertex positions for animated models
10659 v3f = decalsystem->vertex3f;
10660 c4f = decalsystem->color4f;
10661 t2f = decalsystem->texcoord2f;
10662 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10664 if (!decal->color4f[0][3])
10667 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10670 // update color values for fading decals
10671 if (decal->lived >= cl_decals_time.value)
10672 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10676 c4f[ 0] = decal->color4f[0][0] * alpha;
10677 c4f[ 1] = decal->color4f[0][1] * alpha;
10678 c4f[ 2] = decal->color4f[0][2] * alpha;
10680 c4f[ 4] = decal->color4f[1][0] * alpha;
10681 c4f[ 5] = decal->color4f[1][1] * alpha;
10682 c4f[ 6] = decal->color4f[1][2] * alpha;
10684 c4f[ 8] = decal->color4f[2][0] * alpha;
10685 c4f[ 9] = decal->color4f[2][1] * alpha;
10686 c4f[10] = decal->color4f[2][2] * alpha;
10689 t2f[0] = decal->texcoord2f[0][0];
10690 t2f[1] = decal->texcoord2f[0][1];
10691 t2f[2] = decal->texcoord2f[1][0];
10692 t2f[3] = decal->texcoord2f[1][1];
10693 t2f[4] = decal->texcoord2f[2][0];
10694 t2f[5] = decal->texcoord2f[2][1];
10696 // update vertex positions for animated models
10697 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10699 e = rsurface.modelelement3i + 3*decal->triangleindex;
10700 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10701 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10702 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10706 VectorCopy(decal->vertex3f[0], v3f);
10707 VectorCopy(decal->vertex3f[1], v3f + 3);
10708 VectorCopy(decal->vertex3f[2], v3f + 6);
10711 if (r_refdef.fogenabled)
10713 alpha = RSurf_FogVertex(v3f);
10714 VectorScale(c4f, alpha, c4f);
10715 alpha = RSurf_FogVertex(v3f + 3);
10716 VectorScale(c4f + 4, alpha, c4f + 4);
10717 alpha = RSurf_FogVertex(v3f + 6);
10718 VectorScale(c4f + 8, alpha, c4f + 8);
10729 r_refdef.stats.drawndecals += numtris;
10731 // now render the decals all at once
10732 // (this assumes they all use one particle font texture!)
10733 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);
10734 // R_Mesh_ResetTextureState();
10735 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10736 GL_DepthMask(false);
10737 GL_DepthRange(0, 1);
10738 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10739 GL_DepthTest(true);
10740 GL_CullFace(GL_NONE);
10741 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10742 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10743 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10747 static void R_DrawModelDecals(void)
10751 // fade faster when there are too many decals
10752 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10753 for (i = 0;i < r_refdef.scene.numentities;i++)
10754 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10756 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10757 for (i = 0;i < r_refdef.scene.numentities;i++)
10758 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10759 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10761 R_DecalSystem_ApplySplatEntitiesQueue();
10763 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10764 for (i = 0;i < r_refdef.scene.numentities;i++)
10765 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10767 r_refdef.stats.totaldecals += numdecals;
10769 if (r_showsurfaces.integer)
10772 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10774 for (i = 0;i < r_refdef.scene.numentities;i++)
10776 if (!r_refdef.viewcache.entityvisible[i])
10778 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10779 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10783 extern cvar_t mod_collision_bih;
10784 void R_DrawDebugModel(void)
10786 entity_render_t *ent = rsurface.entity;
10787 int i, j, k, l, flagsmask;
10788 const msurface_t *surface;
10789 dp_model_t *model = ent->model;
10792 switch(vid.renderpath)
10794 case RENDERPATH_GL11:
10795 case RENDERPATH_GL13:
10796 case RENDERPATH_GL20:
10798 case RENDERPATH_D3D9:
10799 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10801 case RENDERPATH_D3D10:
10802 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10804 case RENDERPATH_D3D11:
10805 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10807 case RENDERPATH_SOFT:
10808 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10810 case RENDERPATH_GLES2:
10811 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10815 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10817 // R_Mesh_ResetTextureState();
10818 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10819 GL_DepthRange(0, 1);
10820 GL_DepthTest(!r_showdisabledepthtest.integer);
10821 GL_DepthMask(false);
10822 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10824 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10828 qboolean cullbox = ent == r_refdef.scene.worldentity;
10829 const q3mbrush_t *brush;
10830 const bih_t *bih = &model->collision_bih;
10831 const bih_leaf_t *bihleaf;
10832 float vertex3f[3][3];
10833 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10835 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10837 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10839 switch (bihleaf->type)
10842 brush = model->brush.data_brushes + bihleaf->itemindex;
10843 if (brush->colbrushf && brush->colbrushf->numtriangles)
10845 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);
10846 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10847 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10850 case BIH_COLLISIONTRIANGLE:
10851 triangleindex = bihleaf->itemindex;
10852 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10853 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10854 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10855 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);
10856 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10857 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10859 case BIH_RENDERTRIANGLE:
10860 triangleindex = bihleaf->itemindex;
10861 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10862 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10863 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10864 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);
10865 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10866 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10872 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10874 if (r_showtris.integer || (r_shownormals.value != 0))
10876 if (r_showdisabledepthtest.integer)
10878 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10879 GL_DepthMask(false);
10883 GL_BlendFunc(GL_ONE, GL_ZERO);
10884 GL_DepthMask(true);
10886 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10888 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10890 rsurface.texture = R_GetCurrentTexture(surface->texture);
10891 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10893 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10894 if (r_showtris.value > 0)
10896 if (!rsurface.texture->currentlayers->depthmask)
10897 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10898 else if (ent == r_refdef.scene.worldentity)
10899 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10901 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10902 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10903 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10905 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10908 if (r_shownormals.value < 0)
10910 qglBegin(GL_LINES);
10911 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10913 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10914 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10915 qglVertex3f(v[0], v[1], v[2]);
10916 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10917 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10918 qglVertex3f(v[0], v[1], v[2]);
10923 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10925 qglBegin(GL_LINES);
10926 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10928 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10929 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10930 qglVertex3f(v[0], v[1], v[2]);
10931 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10932 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10933 qglVertex3f(v[0], v[1], v[2]);
10937 qglBegin(GL_LINES);
10938 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10940 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10941 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10942 qglVertex3f(v[0], v[1], v[2]);
10943 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10944 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10945 qglVertex3f(v[0], v[1], v[2]);
10949 qglBegin(GL_LINES);
10950 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10952 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10953 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10954 qglVertex3f(v[0], v[1], v[2]);
10955 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10956 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10957 qglVertex3f(v[0], v[1], v[2]);
10964 rsurface.texture = NULL;
10968 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10969 int r_maxsurfacelist = 0;
10970 const msurface_t **r_surfacelist = NULL;
10971 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10973 int i, j, endj, flagsmask;
10974 dp_model_t *model = r_refdef.scene.worldmodel;
10975 msurface_t *surfaces;
10976 unsigned char *update;
10977 int numsurfacelist = 0;
10981 if (r_maxsurfacelist < model->num_surfaces)
10983 r_maxsurfacelist = model->num_surfaces;
10985 Mem_Free((msurface_t**)r_surfacelist);
10986 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10989 RSurf_ActiveWorldEntity();
10991 surfaces = model->data_surfaces;
10992 update = model->brushq1.lightmapupdateflags;
10994 // update light styles on this submodel
10995 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
10997 model_brush_lightstyleinfo_t *style;
10998 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11000 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11002 int *list = style->surfacelist;
11003 style->value = r_refdef.scene.lightstylevalue[style->style];
11004 for (j = 0;j < style->numsurfaces;j++)
11005 update[list[j]] = true;
11010 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11014 R_DrawDebugModel();
11015 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11019 rsurface.lightmaptexture = NULL;
11020 rsurface.deluxemaptexture = NULL;
11021 rsurface.uselightmaptexture = false;
11022 rsurface.texture = NULL;
11023 rsurface.rtlight = NULL;
11024 numsurfacelist = 0;
11025 // add visible surfaces to draw list
11026 for (i = 0;i < model->nummodelsurfaces;i++)
11028 j = model->sortedmodelsurfaces[i];
11029 if (r_refdef.viewcache.world_surfacevisible[j])
11030 r_surfacelist[numsurfacelist++] = surfaces + j;
11032 // update lightmaps if needed
11033 if (model->brushq1.firstrender)
11035 model->brushq1.firstrender = false;
11036 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11038 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11042 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11043 if (r_refdef.viewcache.world_surfacevisible[j])
11045 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11047 // don't do anything if there were no surfaces
11048 if (!numsurfacelist)
11050 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11053 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11055 // add to stats if desired
11056 if (r_speeds.integer && !skysurfaces && !depthonly)
11058 r_refdef.stats.world_surfaces += numsurfacelist;
11059 for (j = 0;j < numsurfacelist;j++)
11060 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11063 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11066 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11068 int i, j, endj, flagsmask;
11069 dp_model_t *model = ent->model;
11070 msurface_t *surfaces;
11071 unsigned char *update;
11072 int numsurfacelist = 0;
11076 if (r_maxsurfacelist < model->num_surfaces)
11078 r_maxsurfacelist = model->num_surfaces;
11080 Mem_Free((msurface_t **)r_surfacelist);
11081 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11084 // if the model is static it doesn't matter what value we give for
11085 // wantnormals and wanttangents, so this logic uses only rules applicable
11086 // to a model, knowing that they are meaningless otherwise
11087 if (ent == r_refdef.scene.worldentity)
11088 RSurf_ActiveWorldEntity();
11089 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11090 RSurf_ActiveModelEntity(ent, false, false, false);
11092 RSurf_ActiveModelEntity(ent, true, true, true);
11093 else if (depthonly)
11095 switch (vid.renderpath)
11097 case RENDERPATH_GL20:
11098 case RENDERPATH_D3D9:
11099 case RENDERPATH_D3D10:
11100 case RENDERPATH_D3D11:
11101 case RENDERPATH_SOFT:
11102 case RENDERPATH_GLES2:
11103 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11105 case RENDERPATH_GL13:
11106 case RENDERPATH_GL11:
11107 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11113 switch (vid.renderpath)
11115 case RENDERPATH_GL20:
11116 case RENDERPATH_D3D9:
11117 case RENDERPATH_D3D10:
11118 case RENDERPATH_D3D11:
11119 case RENDERPATH_SOFT:
11120 case RENDERPATH_GLES2:
11121 RSurf_ActiveModelEntity(ent, true, true, false);
11123 case RENDERPATH_GL13:
11124 case RENDERPATH_GL11:
11125 RSurf_ActiveModelEntity(ent, true, false, false);
11130 surfaces = model->data_surfaces;
11131 update = model->brushq1.lightmapupdateflags;
11133 // update light styles
11134 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11136 model_brush_lightstyleinfo_t *style;
11137 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11139 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11141 int *list = style->surfacelist;
11142 style->value = r_refdef.scene.lightstylevalue[style->style];
11143 for (j = 0;j < style->numsurfaces;j++)
11144 update[list[j]] = true;
11149 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11153 R_DrawDebugModel();
11154 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11158 rsurface.lightmaptexture = NULL;
11159 rsurface.deluxemaptexture = NULL;
11160 rsurface.uselightmaptexture = false;
11161 rsurface.texture = NULL;
11162 rsurface.rtlight = NULL;
11163 numsurfacelist = 0;
11164 // add visible surfaces to draw list
11165 for (i = 0;i < model->nummodelsurfaces;i++)
11166 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11167 // don't do anything if there were no surfaces
11168 if (!numsurfacelist)
11170 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11173 // update lightmaps if needed
11177 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11182 R_BuildLightMap(ent, surfaces + j);
11187 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11189 R_BuildLightMap(ent, surfaces + j);
11190 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11192 // add to stats if desired
11193 if (r_speeds.integer && !skysurfaces && !depthonly)
11195 r_refdef.stats.entities_surfaces += numsurfacelist;
11196 for (j = 0;j < numsurfacelist;j++)
11197 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11200 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11203 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11205 static texture_t texture;
11206 static msurface_t surface;
11207 const msurface_t *surfacelist = &surface;
11209 // fake enough texture and surface state to render this geometry
11211 texture.update_lastrenderframe = -1; // regenerate this texture
11212 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11213 texture.currentskinframe = skinframe;
11214 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11215 texture.offsetmapping = OFFSETMAPPING_OFF;
11216 texture.offsetscale = 1;
11217 texture.specularscalemod = 1;
11218 texture.specularpowermod = 1;
11220 surface.texture = &texture;
11221 surface.num_triangles = numtriangles;
11222 surface.num_firsttriangle = firsttriangle;
11223 surface.num_vertices = numvertices;
11224 surface.num_firstvertex = firstvertex;
11227 rsurface.texture = R_GetCurrentTexture(surface.texture);
11228 rsurface.lightmaptexture = NULL;
11229 rsurface.deluxemaptexture = NULL;
11230 rsurface.uselightmaptexture = false;
11231 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11234 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)
11236 static msurface_t surface;
11237 const msurface_t *surfacelist = &surface;
11239 // fake enough texture and surface state to render this geometry
11240 surface.texture = texture;
11241 surface.num_triangles = numtriangles;
11242 surface.num_firsttriangle = firsttriangle;
11243 surface.num_vertices = numvertices;
11244 surface.num_firstvertex = firstvertex;
11247 rsurface.texture = R_GetCurrentTexture(surface.texture);
11248 rsurface.lightmaptexture = NULL;
11249 rsurface.deluxemaptexture = NULL;
11250 rsurface.uselightmaptexture = false;
11251 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);